Is there a good way of moving a captured variable out of a closure without cloning it? I have a situation similar to this:
let mut partial_result = String::new();
let mut final_results = vec![];
// Some iterator on which 'for_each' is called
(0..15).for_each(|_| {
partial_result.push('a'); // builds the partial result further
if partial_result.len() > 5 { // condition for when the partial result is done
// save and reset partial_result
final_results.push(partial_result)
partial_result = String::new();
}
});
println!("Result: {final_results:?}");
However as is this causes an error. I would like final_results to take over ownership of the current value in partial_result and then reset partial_result back to it's starting value. In this simple example it can be solved by calling .clone() on partial_result before pushing it. However in the actual code I have some structs which don't necessarily implement Clone<T> so I was wondering if there is some clever way of moving the current value and then immediately resting it to a fixed value in Rust or if I have to make partial_result clonable?
You will need to create a new allocation, but you can clear the string simultaneously and without moving using drain:
fn main() {
let mut partial_result = String::new();
let mut final_results = vec![];
// Some iterator on which 'for_each' is called
(0..15).for_each(|_| {
partial_result.push('a'); // builds the partial result further
if partial_result.len() > 5 {
// condition for when the partial result is done
// save and reset partial_result
final_results.push(partial_result.drain(..).collect::<String>());
}
});
println!("Result: {final_results:?}");
}
Option::take can also be useful if you need at least one element to meaningfully initialize the accumulator, or if you know that you’ll only ever be producing a single value.