Selective Closure Capture in Rust

Written — Updated
  • Sometimes in Rust you may have a closure that needs to move some values but not others. If all the values satisfy the Copy this is easy, but that it usually not the case.
  • Sometimes we need to move some values into a closure, but want to borrow others.
  • You can solve this problem by creating new bindings for the by-reference values, so that the closure moves the references instead of the original value. It's not pretty but it works well.
  • let threads = vec![("referrers", "s"), ("referrals", "o")];
    thread::scope(|s| {
        for (description, field) in threads {
            // Get variables explicitly as references so that the closure
            // moves only the references.
            let idmapper = &idmapper;
            let input_path = &input_path;
            let output_path = &output_path;
            let logger = &logger;
            let file_prefix = &file_prefix;
            s.spawn(move |_| {
                write_relationships_table(
                    &logger,
                    &idmapper,
                    description,
                    &input_path,
                    &output_path,
                    file_prefix.as_str(),
                    field,
                    max_year,
                );
            });
        }
    })
    .unwrap();
  • This is done by making it a move closure, and rebinding the variables that we want to borrow as references.

Thanks for reading! If you have any questions or comments, please send me a note on Twitter. And if you enjoyed this, I also have a newsletter where I write about tech thoughts, interesting things I've read, and project updates each Thursday.

You can check out a recent issue, or enter your email below to subscribe.