Guide

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()); // None

next 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(); // runs

Rust warns you when an iterator is built and never used.

iter, iter_mut, into_iter

MethodGives youThe Vec after
iter()&Tstill usable
iter_mut()&mut Tstill usable, maybe changed
into_iter()Tmoved, 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 fine

for x in &mut v is the same as v.iter_mut().

Remember

  • next gives Some(item), then None.
  • Adapters are lazy; a consumer makes them run.
  • for x in v moves v; write &v to borrow it.