Iterators
An iterator hands out items one at a time.
Iterator and next
Every iterator has a next method. It returns Some(item) while there are items, then None.
let v = vec![1, 2];let mut it = v.iter();println!("{:?}", it.next()); // Some(1)println!("{:?}", it.next()); // Some(2)println!("{:?}", it.next()); // Nonenext changes the iterator's position, so the iterator must be mut.
Iterator is a trait. To make your own iterator, write type Item (the type it hands out, like type Target in Deref) and a next method:
struct Count(u32);impl Iterator for Count { type Item = u32; fn next(&mut self) -> Option<u32> { self.0 += 1; if self.0 <= 2 { Some(self.0) } else { None } }}Iterators are lazy
Two methods you will meet in the next unit: map(|x| x * 2) runs a closure on each item, and sum() adds all the items up (give the result a type, like let t: i32).
Methods like map build a new iterator, but they do no work by themselves. Nothing runs until something asks for items, like a for loop or sum.
let v = vec![1, 2, 3];v.iter().map(|x| x * 2); // does nothinglet t: i32 = v.iter().map(|x| x * 2).sum(); // runsRust warns you when an iterator is built and never used.
iter, iter_mut, into_iter
| Method | Gives you | The Vec after |
|---|---|---|
iter() | &T | still usable |
iter_mut() | &mut T | still usable, maybe changed |
into_iter() | T | moved, gone |
let mut v = vec![1, 2];for x in v.iter_mut() { *x *= 10;}println!("{:?}", v); // [10, 20]for uses iterators
for x in v calls v.into_iter(). That moves v, so you can't use it after the loop (error E0382). Loop over a borrow to keep it:
let v = vec![1, 2];for x in &v { // same as v.iter() println!("{x}");}println!("{:?}", v); // still finefor x in &mut v is the same as v.iter_mut().
Remember
nextgivesSome(item), thenNone.- Adapters are lazy; a consumer makes them run.
for x in vmovesv; write&vto borrow it.