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.