Is there a way to have a Rust closure that moves only some variables into it? Is there a way to have a Rust closure that moves only some variables into it? multithreading multithreading

Is there a way to have a Rust closure that moves only some variables into it?


Yes, it is possible to move only one or some variables into a closure (rather than all or none).

Yes, this can be used to "circumvent" reference counting.

I found an answer in the documentation of rayon::scope that turns out to be exactly about this problem: 'Accessing the stack data [from within a scoped threads scope]'. That page also has an example that is clearer than the pseudocode in this question.

It turns out that you can either:

  • Use a move closure but refer to variables in the outer scope by shadowing them with a reference, therefore capturing them by reference rather than by value, using let settings = &settings:

    crossbeam::scope(|scope| {    let settings = &settings; // refer to outer variable by reference    for score in 0..MAX_FEASIBLE_SCORE {        scope.spawn(move |_| {            let work_result = do_cool_computation(settings, score);            println!("{:?}", work_result);        });    }}).unwrap();
  • Use a normal closure, and only move the required variables by shadowing them inside the closure using let score = score:

    crossbeam::scope(|scope| {    for score in 0..MAX_FEASIBLE_SCORE {        scope.spawn(|_| {            let score = score; // capture only score            let work_result = do_cool_computation(&settings, score);            println!("{:?}", work_result);        });    }}).unwrap();


The closure! macro gives the ability to selectively reference, move, or clone variables into a closure.

Example taken from the docs:

use closure::closure;let string = "move".to_string();let x = 10;let mut y = 20;let rc = Rc::new(5);let closure = closure!(move string, ref x, ref mut y, clone rc, |arg: i32| {    ...});

Variables that are captured but not listed default to being moved.