DEV Community

Discussion on: Struct callback.

Collapse
 
adam_cyclones profile image
Adam Crockett 🌀 • Edited

Ben to the rescue again, I will give it a shot (and read about RC) as soon as I'm home. Currently on a crowded train trying to look busy 😅

Collapse
 
deciduously profile image
Ben Lovy

My Rust senses were tingling :)

Thread Thread
 
adam_cyclones profile image
Adam Crockett 🌀 • Edited

Hey Ben, I am just revisiting this.

pub struct Callback<T> {
    f: Rc<dyn Fn(&str) -> T>,
}

impl<T> Callback<T> {
    /// Call this callback
    pub fn call(&self, token: &str) -> T {
        return (self.f)(token);
    }
}

impl<T> Clone for Callback<T> {
    fn clone(&self) -> Self {
        Self {
            f: Rc::clone(&self.f),
        }
    }
}

impl<T, F: Fn(&str) -> T + 'static> From<F> for Callback<T> {
    fn from(func: F) -> Self {
        Self { f: Rc::new(func) }
    }
}

struct ASTNode {
    id: GRAM,
    allow_next: Vec<GRAM>,
    foo: &'static str,
    matcher: Callback<bool>
}


// Usage

fn is_import_statement (token: &str) -> bool {    
    // TBA
    return true;
}

let x = ASTNode{
    id: GRAM::IMPORT_STATEMENT,
    foo: "hey",
    identify_statement_from_next: vec!(
        GRAM::L_C_BRACE,
        GRAM::L_P_BRACKET,
        GRAM::NAME,
        GRAM::ASTERISK
    ),
    matcher: Callback::from(is_import_statement)
};

x.matcher.call("@import");

How can I access self.foo from is_import_statement where self which comes from the ASTNode struct.

Thread Thread
 
deciduously profile image
Ben Lovy • Edited

Hrm. At a glance, I'm not positive you can nor should be able to. The callback won't be able to access any context not provided at instantiation, you'd need to accept an additional argument like dyn Fn(&str,&str), which is usually how I skirt around this sort of thing in Rust. The callback has no concept of any parent object that owns it. I might not fully understand the context here, though - there always is a way to do what you want but not always with the structure you thought.

Do you have a fuller code sample I could play with? Might not get there tonight but can play with it this weekend.

Maybe the callback struct could also contain a &'a ASTNode referencing the parent, passed in to the constructor, but it gets messy. You'd probably shift away from the From trait and just provide a Callback::new().

Thread Thread
 
deciduously profile image
Ben Lovy • Edited

Also, the /r/learnrust subreddit is small, but generally helpful, and the main /r/rust subreddit may help you too. They're pretty intense, but highly knowledgeable and you may be pushing the edge of what I understand - not that I'm not curious to learn this solution.

 
adam_cyclones profile image
Adam Crockett 🌀

Oh I made a few tweeks and ended up doing this

x.matcher.call(&x ,"@import");

so thats kind of what I wanted... not as nice a real relationship between the callback and the struct it lives in.

Thread Thread
 
deciduously profile image
Ben Lovy

yup, that was my first thought but I agree, not what you're gunning for. Maybe try the stored reference?

Thread Thread
 
adam_cyclones profile image
Adam Crockett 🌀 • Edited

I think I can live with it tbh, it works well. Ultimately I can progress to the next bit of Jess's lexer. This part of the code isn't committed yet, the whole solution is a bit higldy pigldy. Sorry to rubber duck, I find writing about problems is enormously helpful.

I will check out the communities you suggested and such 😁.

Thank you so much once again.

Thread Thread
 
deciduously profile image
Ben Lovy

Don't apologise! I get a lot out of it too, and think you've got a cool project going on.