In this code:
fn main() {
let my_vec = vec![1,2,3,4,5,6,7,8];
let mut pair: Vec<Vec<u8>> = vec![vec![], vec![]];
let mut my_vec_iter = my_vec.into_iter();
// pair.iter_mut().for_each(|v| v.append(&mut my_vec_iter.take(4).collect()));
// error[E0507]: cannot move out of `my_vec_iter`, a captured variable in an `FnMut` closure
let my_ref = &mut my_vec_iter;
pair.iter_mut().for_each(|v| v.append(&mut my_ref.take(4).collect()));
println!("{:?}", pair);
}
The commented-out line doesn't compile, because (as I understand it) take() takes ownership of its receiver and you can't do that with a captured variable.
But the alternative version, where the captured variable is &mut my_vec_iter, does work, and I don't understand what's going on. I haven't been able to find a version of take(&mut self), so presumably it's still calling take(self)?
Explain like I'm 5 - how come taking an explicit mutable reference stops take taking ownership? Or, if I've misunderstood something, what is going on?
This works because Iterator is also implemented for references with this impl.
impl<I> Iterator for &mut I
where
I: Iterator + ?Sized,
Iterator::take always takes self, but you can use either I or &mut I as the type of self.
There's also a convenience method on Iterator just for obtaining a &mut self reference, so you don't need to make another binding or contend with operator precedence: Iterator::by_ref.
// these are identical
my_vec_iter.by_ref().take(4)
(&mut my_vec_iter).take(4)
You should also use extend when appending from an iterator. This avoids allocating a temporary Vec.
pair.iter_mut().for_each(|v| v.extend(my_vec_iter.by_ref().take(4)));