C.W.K.
Stream
Lesson 05 of 06 · published

Iterators & Adapters

~12 min · collections, iterators, adapters, lazy

Level 0Rust Curious
0 XP0/80 lessons0/19 achievements
0/100 XP to next level100 XP to go0% complete

Iterators are how Rust does loops without writing loops. The Iterator trait you met in the Traits track powers a whole vocabulary of adapters and consumers that read like a description of what you want, not how to compute it.

Getting an iterator

Three ways to iterate a collection: .iter() yields shared references (&T), .iter_mut() yields mutable references (&mut T), and .into_iter() consumes the collection, yielding owned T. Which you pick is — again — the ownership question: borrow to read, borrow-mut to modify, consume to take ownership.

Adapters vs consumers

Adapters like map, filter, take, skip transform one iterator into another — and they're lazy, doing no work until driven. Consumers like collect, sum, count, fold, or a for loop are what actually pull values through and produce a result. A chain of adapters with no consumer does nothing at all.

Adapters are lazy; consumers drive the work. v.iter().map(f).filter(g) builds a recipe and runs nothing. Add .collect() or .sum() and the whole chain executes in a single pass, with the adapters fused together — no intermediate vectors, as fast as a hand-written loop.

Why prefer iterators over loops

An iterator chain says what you want — 'the squares of the even numbers' — while an index loop says how to compute it, with room for off-by-one bugs. Iterators are also zero-cost: the compiler optimizes a chain down to the same machine code as the hand-written loop, often faster. clippy will actively nudge you from manual loops toward iterator chains.

Code

A lazy adapter chain driven by sum()·rust
fn main() {
    let nums = vec![1, 2, 3, 4, 5, 6];

    // Lazy adapters + a consumer (sum) that drives them:
    let sum_of_even_squares: i32 = nums
        .iter()                   // &i32
        .filter(|&&n| n % 2 == 0) // keep evens
        .map(|&n| n * n)          // square them
        .sum();                   // consumer: runs the whole chain in one pass
    println!("{sum_of_even_squares}"); // 4 + 16 + 36 = 56
}

External links

Exercise

Given a Vec<i32>, build a chain that keeps the negative numbers, takes their absolute value, and collects them into a new Vec<i32>. Confirm nothing runs until .collect(). Then write the same logic as an imperative for loop with a manual push — which reads more clearly to you, and which would clippy prefer?
Hint
The chain .iter().filter(...).map(...).collect() is declarative and fuses into one pass. clippy nudges toward iterator chains over manual loops because they're harder to get wrong and just as fast.

Progress

Progress is local-only — sign in to sync across devices.
Spotted a bug or have feedback on this page?Report an Issue

Comments 0

🔔 Reply notifications (sign in)
Sign inPlease sign in to comment.

No comments yet — be the first.