LiveDuo
1
Is there a way to avoid creating temporary variables a variable is captured in multiple closures:
- The
move
keyword in the closures is required
- It's fine to use any other container instead of Rc as long as the inner value is passed to the closures
- It's fine to clone the container, I tried the
Copy
trait but does not work as the inner value is a struct
use std::rc::Rc;
use std::cell::RefCell;
#[derive(Debug)]
struct MyStruct { value: u32 }
fn main() {
let shared = Rc::new(RefCell::new(MyStruct { value: 42}));
let shared_clone_1 = shared.clone(); // clone 1
let shared_clone_2 = shared.clone(); // clone 2
let shared_clone_3 = shared.clone(); // clone 3
let shared_clone_4 = shared.clone(); // clone 4: can these clones be hidden?
let closure_1 = move || { println!("closure_1 {:?}", shared); };
let closure_2 = move || { println!("closure_2 {:?}", shared_clone_1); };
let closure_3 = move || { println!("closure_3 {:?}", shared_clone_2); };
let closure_4 = move || { println!("closure_4 {:?}", shared_clone_3); };
let closure_5 = move || { println!("closure_5 {:?}", shared_clone_4); };
closure_1();
closure_2();
closure_3();
closure_4();
closure_5();
}
For the code given, you can capture a reference instead.
LiveDuo
4
I haven't thought of it that way but it means the following can be done:
let shared = &MyStruct { value: 42};
let closure_1 = move || { println!("closure_1 {:?}", shared); };
let closure_2 = move || { println!("closure_2 {:?}", shared); };
let closure_3 = move || { println!("closure_3 {:?}", shared); };
let closure_4 = move || { println!("closure_4 {:?}", shared); };
let closure_5 = move || { println!("closure_5 {:?}", shared); };
LiveDuo
5
That was very helpful, let to the following comment:
Which pointed to this solution:
let shared = MyStruct { value: 42};
let shared_fn = || { shared.clone() };
let closure_1 = move || { println!("closure_1 {:?}", shared_fn()); };
let closure_2 = move || { println!("closure_2 {:?}", shared_fn()); };
let closure_3 = move || { println!("closure_3 {:?}", shared_fn()); };
let closure_4 = move || { println!("closure_4 {:?}", shared_fn()); };
let closure_5 = move || { println!("closure_5 {:?}", shared_fn()); };
1 Like
One other technique you can make use of is a combination of shadowing in a new scope to avoid having to give things a dummy variable name. Described in detail here: Rust Atomics and Locks — Chapter 1. Basics of Rust Concurrency
3 Likes
LiveDuo
7
Turns out this is possible with arena allocators. Opened a new topic here: