I have found a way to move context into several closures, but it looks ugly. I do it with help of Rc and cloning each variable I need to use for each closure. Particularly I don't like to clone every variable for every closure I want to use:
It is an extensive way to go and I feel there must be a better way to do it?
Also, uncommenting line // context_clone_1.a += 1; breaks the program.
What is the proper way of solving problems like this in Rust?
If you want to avoid this kind of stuff, you need to stop using callbacks. If you must use callbacks, Rc is more or less unavoidable. That said, I've seen some people build macros that can insert the clones for you.
To enable modification of the shared value, you can use Cell or RefCell either around the entire struct or the fields of the struct.
In my opinion, a loop with a match on an event type often produces nicer code in Rust, because it integrates more nicely with the ownership model of Rust. You don't need to mess with shared values like what callbacks force you to.
@alice is not it suboptimal to have a match for each instance of an event? Let's say I have a thousand types of events and only a few types have registered callbacks. Is not it suboptimal to put every event in the queue and use match?
It's not much different than registering a thousand event listeners just above the loop is it? If you only need to handle a few events, you can simply add an _ => {} case to the match.
Well it depends on how the event listeners are triggered, but the match probably compiles down to some sort of binary search, so finding the right branch takes 10 comparisons if you have 1000 branches. It may even compile to a jump table, in which case it would take a single array lookup and a goto.