3 ms·
Imagine this fairly basic situation: you have a button object. When clicked, it triggers a closure (callback). And that closure needs to change the button's tex
by amelius 5mo ago
Imagine this fairly basic situation: you have a button object. When clicked, it triggers a closure (callback). And that closure needs to change the button's text to e.g. "Clicked!".
To do this in Rust, the closure needs a mutable reference to the button. However, the GUI event loop also needs a reference to the button to draw it on the screen. In Rust, you can have many immutable references, __or__ exactly one mutable reference, but never both at the same time. Since the GUI framework holds the button, it won't let your closure mutably borrow it at the same time.
- veidelis 5mo agoDo you find anything "bad" about this code solving the problem? use std::rc::Rc; use std::cell::RefCell; struct Button { text: String, on_click: Option<Rc<dyn Fn()>>, } impl Button { fn new(text: &str) -> Self { Button { text: text.to_string(), on_click: None } } fn draw(&self) { println!("[Button: \"{}\"]", self.text); } fn fire_click(button: &Rc<RefCell<Button>>) { let cb = button.borrow().on_click.clone(); if let Some(cb) = cb { cb(); } } } fn main() { let button = Rc::new(RefCell::new(Button::new("Click me"))); let cb_handle = Rc::clone(&button); button.borrow_mut().on_click = Some(Rc::new(move || { cb_handle.borrow_mut().text = "Clicked!".to_string(); })); button.borrow().draw(); Button::fire_click(&button); button.borrow().draw(); } Prints: [Button: "Click me"] [Button: "Clicked!"]
- CyberDildonics 5mo agoWhy would they need them at the same time? The overall state will contain the button. Many interactive programs can be GetInput(); ChangeState(); DrawState(); Why wouldn't their lifetimes be isolated? Also the drawing doesn't need a mutable reference.