[SOLVED] Share dynamic variables between user defined fn() variables


#1

Hi everyone

I have a question! how to make variables in parent scope accessible for child scopes dynamically, something like this:

they all live in the same thread and called sequentially:

pub struct app {
    pub init: fn(),
    pub create: fn(),
    pub update: fn()
}
impl app {
    pub fn run(&mut self) {
        (self.init)();
        // create
        (self.create)();
        // loop
        loop {
            (self.init)();
        }
    }
}

fn main() {

    let some = shader{};

    fn init(){
        println!("{}", "initialized.");
    }

    fn create(){
        println!("{}", "created.");
        some.compile(); // --------------> i want this to be accessible
    }

    fn update(){
        println!("{}", "looping");
        some.useHere(); // ----------------> and here
    }
    let mut x = app{
        init: init,
        create: create,
        update: update
    };
    x.run();
}

here is the source:


#2

I think you should use a move closure and Rc<Cell<T>> or similar.


#3

actually, I did use Rcs but still getting this error,
it says use closures instead but when I come up with closures I can’t make structure like this:

let shd = std::rc::Rc::new(shader::new(b"
        #version 140

        in vec3 position;

        uniform mat4 model;
        uniform mat4 view;
        uniform mat4 projection;

        void main() {
            gl_Position = projection * view * model * vec4(position, 1.0);
        }
    \0",b"
        #version 140
        out vec4 color;
        void main() {
            color = vec4(1,1,0,0.5);
        }
    \0"));

or maybe you know better idea, i’m newbie


#4

Here’s something to get you started perhaps:

pub struct app<'a> {
    pub init: Box<Fn() + 'a>,
    pub create: Box<Fn() + 'a>,
    pub update: Box<Fn() + 'a>
}

fn main() {
    let some = shader{};
    let init = Box::new(|| println!("{}", "initialized."));
    let create = Box::new(|| {
        println!("{}", "created.");
        some.compile();
    });
    let update = Box::new(|| {
        println!("{}", "looping");
        some.useHere();
    });

    let mut x = app{
        init: init,
        create: create,
        update: update
    };
    x.run();
}

#5

it worked! thank you so much buddy. :grin:
i commit these last lines, to project, awesome answer :sunglasses:


#6

Instead of storing closures, you can also use a trait:

pub trait App {
    fn init(&mut self);
    fn create(&mut self);
    fn update(&mut self);
    
    // I've made `run` a default method of App,
    // You can also make it a freestanding function
    // that takes any A: App
    fn run(&mut self) {
        self.init();
        self.create();
        for _ in 0..10 {
            self.update();
        }
    }
}

Full playground


#7

I tried both solutions, and they do the job perfectly,
but I don’t know exactly which one is a better way?
have you looked at my project at github?