iwantcoding.com
🔥 Daily 👥 Rooms 🏆 Top Log in Sign up

Iterators

Rust iterators are lazy + zero-cost. Chain operations with .map / .filter / .fold; nothing runs until a consumer (.collect, .sum, for) drives the chain.

Adapters, consumers, custom iterators

EXAMPLE
// 1) Standard chain
let nums = vec![1, 2, 3, 4, 5];

let sum_of_squares: i32 = nums.iter()
    .map(|x| x * x)
    .filter(|x| x % 2 == 1)
    .sum();
// 1 + 9 + 25 = 35

// 2) Three flavours of iter — borrow, mutable, owned
for x in nums.iter()    { /* &i32 */ }
for x in nums.iter_mut(){ *x += 1;  } // mutate in place (needs `let mut nums`)
for x in nums.into_iter(){ /* i32, consumes the vec */ }

// 3) Common adapters
let doubled: Vec<i32> = (1..=5).map(|x| x * 2).collect();
let evens:   Vec<i32> = (1..=20).filter(|x| x % 2 == 0).collect();
let first5:  Vec<i32> = (1..).take(5).collect();
let skip3:   Vec<i32> = (1..=10).skip(3).collect();
let enumed:  Vec<(usize, i32)> = (10..15).enumerate().collect();
let rev:     Vec<i32> = (1..=5).rev().collect();
let zip:     Vec<(i32, char)> = (1..).zip('a'..).take(5).collect();

// 4) Consumers (terminal operations)
let total:   i32  = (1..=100).sum();
let product: i64  = (1..=10).product();
let count:   usize = (1..).take_while(|x| x * x < 100).count();
let max:     Option<i32> = nums.iter().copied().max();
let min_by:  Option<&str> = words.iter().min_by_key(|s| s.len()).copied();
let first:   Option<&i32> = nums.iter().find(|&&x| x > 3);
let any:     bool = nums.iter().any(|&x| x > 4);
let all:     bool = nums.iter().all(|&x| x > 0);

// 5) Fold (general accumulator)
let sum2: i32 = (1..=100).fold(0, |acc, x| acc + x);
let greet: String = ("abc".chars()).fold(String::new(), |mut s, c| { s.push(c); s });

// 6) Collect into different types
let s: String       = ("abc".chars()).rev().collect();      // "cba"
let v: Vec<_>       = (1..=5).map(|x| x * 2).collect();
let m: HashMap<_,_> = users.iter().map(|u| (u.id, u)).collect();
let set: HashSet<_> = (1..100).filter(|x| x % 3 == 0).collect();

// 7) flat_map — flatten nested results
let words = vec!["hello world", "foo bar"];
let all: Vec<&str> = words.iter().flat_map(|s| s.split_whitespace()).collect();

// flatten — for Iterator<Item = Iterator>
let nested = vec![vec![1, 2], vec![3, 4]];
let flat: Vec<i32> = nested.into_iter().flatten().collect();

// 8) Lazy evaluation — nothing runs until a consumer
let pipeline = (1..)
    .map(|x| {
        println!("processing {}", x);
        x * 2
    })
    .filter(|x| x % 3 == 0);
// Nothing printed yet!

let first_three: Vec<i32> = pipeline.take(3).collect();
// Only processes until we have 3 results — efficient on infinite sequences.

// 9) Iterator over Results — handle errors cleanly
fn parse_all(items: &[&str]) -> Result<Vec<i32>, std::num::ParseIntError> {
    items.iter().map(|s| s.parse::<i32>()).collect()
    // collect::<Result<Vec<_>, _>>() short-circuits on the first Err
}

// 10) Custom iterator — implement Iterator
struct Fibonacci {
    a: u64,
    b: u64,
}

impl Iterator for Fibonacci {
    type Item = u64;
    fn next(&mut self) -> Option<u64> {
        let next = self.a;
        self.a = self.b;
        self.b = next + self.a;
        Some(next)
    }
}

fn fib() -> Fibonacci {
    Fibonacci { a: 0, b: 1 }
}

let first_10: Vec<u64> = fib().take(10).collect();
// [0, 1, 1, 2, 3, 5, 8, 13, 21, 34]

// 11) Parallel iterators — rayon (drop-in)
// use rayon::prelude::*;
// let total: u64 = (1u64..=1_000_000).into_par_iter().filter(is_prime).sum();

// 12) Performance
// Iterator chains compile to the same loop a hand-written for would produce — zero-cost abstraction.
// `cargo bench` to verify; usually nothing to optimise.

Why it matters

Iterator chains in Rust are zero-cost — the compiler inlines them into tight loops. Lean on them: map / filter / collect reads better than the equivalent for loop and runs just as fast.

Tip: Tweak the snippet with Try it Yourself », then sit the quiz at the bottom of the page.

Example

Example
let total: i32 = (1..=5)
    .map(|x| x * x)
    .filter(|x| x % 2 == 1)
    .sum();
println!("{total}");
Try it Yourself »

Discussion

Loading…