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)));