liveBook · Manning

Iterator

As explained in Learn Rust in a Month of Lunches

An iterator is a Rust value implementing the Iterator trait that produces a sequence of items, typically through repeated calls to next.

An iterator gives you items one at a time, rather like dealing cards from a deck. In Rust, a value follows this convention by implementing the Iterator trait. Its central method, next(), returns Some(item) when an item is available and None when there is not one. A for loop handles those repeated requests for you, but you can call next() yourself. section 8.2 section 8.4

fn main() {
    let my_vec = vec!['a', 'b', '거', '柳'];          #1
 
    let mut my_vec_iter = my_vec.iter();             #2
 
    assert_eq!(my_vec_iter.next(), Some(&'a'));      #3
    assert_eq!(my_vec_iter.next(), Some(&'b'));
    assert_eq!(my_vec_iter.next(), Some(&'거'));
    assert_eq!(my_vec_iter.next(), Some(&'柳'));
    assert_eq!(my_vec_iter.next(), None);            #4
    assert_eq!(my_vec_iter.next(), None);            #5
}

Follow each call to next(): the character iterator returns references wrapped in Some, then returns None after its items run out. section 8.2

When starting from a collection, choose how the iterator gets its items:

  • Use .iter() to get references. The original collection remains available. section 8.2
  • Use .iter_mut() to get mutable references, so you can change items. section 8.2
  • Use .into_iter() to get values. Taking values from a vector this way consumes the vector. section 8.2

You can chain methods to describe what you want: skip items, take a few, or use map() with a closure to transform each item. A closure such as |x| x + 1 names the item it receives. Chaining these methods prepares an iterator; it does not necessarily process the items yet. For example, map() alone can produce a compiler warning that the unused iterator must be used. Call a consuming method such as collect() to build a collection, or for_each() to do something with each item. section 8.1 section 8.2 section 8.3.2

Make a new vector

Starting with vec![1, 2, 3], the expression .iter().map(|x| x + 1).collect::<Vec<i32>>() produces [2, 3, 4]. Because iter() borrows the original vector, you can still use it afterward. collect() is the step that turns the transformed iterator into a Vec. section 8.2

You can make your own iterator by implementing Iterator, choosing an Item type, and writing next(&mut self) to return an Option of that type. Keep track of what to produce next in the value’s state. An iterator need not have a natural end: one example always returns Some(1), then uses take(5) and collect() to make a finite vector. This is the practical pattern: produce items through next(), adapt the sequence as needed, and consume it when you want a result. section 8.2 section 8.4

How Learn Rust in a Month of Lunches covers it

How deep it goes
Explains next(), collection iteration choices, lazy consumption, and a custom Iterator implementation; defers broader method coverage.
Examples
Demonstrates repeated next() calls on characters, mapped vectors, a compiler warning for unused map(), and a custom source of ones.
What it assumes
Builds on for loops and vectors while explaining closures and Iterator’s associated type as they appear.
What you can do after
Build it from scratch by implementing Item and next(), or apply iterator methods to transform and collect items.
How it connects
Connects Iterator to for loops, Option, closures, method chaining, ownership, and lazy evaluation.

Also explained in

Compare how 15 books explain iterator →

Related concepts

This explainer was generated by Manning's knowledge graph from the text of Learn Rust in a Month of Lunches. The section links point to the parts of the book it draws on.