thecodex.expert · The Codex Family of Knowledge
Rust

Iterators

An iterator chain does nothing at all until you call something that actually consumes it — map and filter alone produce no output whatsoever.

Rust 1.96 Lazy evaluation Last verified:
Canonical Definition

The Iterator trait requires just one method, next(), which returns Some(item) or None when exhausted. Iterators are lazy: calling .map() or .filter() builds up a chain of transformations but produces no output on its own — nothing runs until a consuming method like .collect(), .sum(), or a for loop actually pulls values through the chain. Because of how the compiler optimizes these chains, iterator code typically compiles to loops just as fast as hand-written ones.

Creating and consuming an iterator

.iter() produces an iterator of references over a collection; a for loop is a consuming method that pulls every item through automatically.

Rustiterator_basics.rs
let v = vec![1, 2, 3];
let mut iter = v.iter();

println!("{:?}", iter.next());   // Some(1)
println!("{:?}", iter.next());   // Some(2)
println!("{:?}", iter.next());   // Some(3)
println!("{:?}", iter.next());   // None — exhausted

for x in v.iter() {              // idiomatic: for loop consumes the iterator
    println!("{}", x);
}

Laziness: nothing happens until you consume

Building a chain of adapters like map and filter creates a description of the work, but performs none of it — the underlying closures are never even called — until a consuming method drives the chain to completion.

Rustlaziness.rs
let v = vec![1, 2, 3, 4, 5];

let chain = v.iter().map(|x| {
    println!("processing {}", x);   // this print never runs yet!
    x * 2
});
// nothing has printed at this point — chain hasn't been consumed

let doubled: Vec<i32> = chain.collect();   // NOW it runs, prints 5 times
println!("{:?}", doubled);   // [2, 4, 6, 8, 10]

Common adapters: map, filter, collect

Adapter methods chain together to express a data transformation declaratively; .collect() is the most common consumer, gathering results into a Vec, String, HashMap, or any type implementing FromIterator.

Rustadapters.rs
let numbers = vec![1, 2, 3, 4, 5, 6];

let result: Vec<i32> = numbers
    .iter()
    .filter(|&&x| x % 2 == 0)   // keep evens: [2, 4, 6]
    .map(|x| x * x)              // square them: [4, 16, 36]
    .collect();

println!("{:?}", result);   // [4, 16, 36]

let total: i32 = numbers.iter().sum();   // consumes directly, no collect needed
println!("{}", total);   // 21

Sources

1
The Rust Project. The Rust Programming Language, "Processing a Series of Items with Iterators", doc.rust-lang.org/book/ch13-02.