In Rust Iterator pattern with iter(), into_iter() and iter_mut() methods I explained why attempting to use a variable holding a Vec
after iterating through it using the for … in
syntax leads to a compilation error.
The post explains why the following code won't compile:
fn main() {
let some_ints = vec![1,2,3,4,5];
// iterating through a vec
for i in some_ints {
dbg!(i);
}
// attempting to use the vec will
// lead to compile error after the iteration
dbg!(some_ints);
}
I then showed 3 methods that can be called before iterating using the for … in
and how 2 of these methods allow the Vec
to still be used even after iteration.
These 3 methods are into_iter()
, iter()
, and iter_mut()
. That is:
#[test]
fn into_iter_demo() {
// the .into_iter() method creates an iterator, v1_iter
// which takes ownership of the values being iterated.
let mut v1_iter = v1.into_iter();
assert_eq!(v1_iter.next(), Some(1));
assert_eq!(v1_iter.next(), Some(2));
assert_eq!(v1_iter.next(), Some(3));
assert_eq!(v1_iter.next(), None);
// If the line below is uncommented, the code won't compile anymore
// this is because, after the iteration, v1 can no longer be used
// since the iteration moved ownership
//dbg!(v1);
}
The two other methods that allow the Vec
to still be used after iteration via for … in
are:
#[test]
fn iter_demo() {
let v1 = vec![1, 2, 3];
// the .iter() method creates an iterator,
// v1_iter which borrows value immutably
let mut v1_iter = v1.iter();
// iter() returns an iterator of slices.
assert_eq!(v1_iter.next(), Some(&1));
assert_eq!(v1_iter.next(), Some(&2));
assert_eq!(v1_iter.next(), Some(&3));
assert_eq!(v1_iter.next(), None);
// because values were borrowed immutably,
// it is still possible to use
// the vec after iteration is done
dbg!(v1);
}
And
#[test]
fn iter_mut_demo() {
let mut v1 = vec![1, 2, 3];
// the .iter_mut() method creates an iterator,
// v1_iter which borrows value and can mutate it.
let mut v1_iter = v1.iter_mut();
// access the first item and multiple it by 2
let item1 = v1_iter.next().unwrap();
*item1 = *item1 * 2;
// access the second item and multiple it by 2
let item2 = v1_iter.next().unwrap();
*item2 = *item2 * 2;
// access the third item and multiple it by 2
let item3 = v1_iter.next().unwrap();
*item3 = *item3 * 2;
// end of the iteration
assert_eq!(v1_iter.next(), None);
// this will print out [2,4,6]
dbg!(v1);
}
In this post, we are going to dive a little bit deeper into understanding some of the machinery that makes the above work.
We start again by talking about the Iterator
trait.