Essential Standard Traits

Iterator

The Iterator trait in std::iter produces a sequence of values one item at a time via .next(), serving as the foundation for for loops and functional data pipelines.

Trait Definition

pub trait Iterator {
    type Item;

    fn next(&mut self) -> Option<Self::Item>;

    // Plus 70+ default adapter and consumer methods:
    // map, filter, take, skip, enumerate, zip, fold, collect, sum, count, ...
}

Every call to next(&mut self) returns Some(item) while elements remain and None once the sequence is exhausted. Implementing Iterator requires defining only the associated type Item and the next method; all iterator adapters (map, filter, take) and consumers (collect, sum, fold) are provided as default methods.

Implementing a Custom Iterator

struct Fibonacci {
    curr: u64,
    next: u64,
}

impl Fibonacci {
    fn new() -> Self {
        Self { curr: 0, next: 1 }
    }
}

impl Iterator for Fibonacci {
    type Item = u64;

    fn next(&mut self) -> Option<Self::Item> {
        let current = self.curr;
        self.curr = self.next;
        self.next = current + self.next;
        Some(current)
    }
}

fn main() {
    let first_eight: Vec<u64> = Fibonacci::new().take(8).collect();
    println!("{first_eight:?}");
}
[0, 1, 1, 2, 3, 5, 8, 13]

Adapters vs. Consumers

Iterator methods fall into two categories:

Category Behavior Examples
Adapters (lazy) Consume self and return a new wrapper iterator without executing any work until polled .map(), .filter(), .take(), .skip(), .enumerate(), .zip(), .chain()
Consumers (eager) Repeatedly call .next() until exhaustion to compute a final value or side effect .collect(), .sum(), .count(), .fold(), .find(), .any(), .all(), .for_each()
Fibonacci::new() ──> .filter(|n| n % 2 == 0) ──> .take(4) ──> .sum::<u64>()
  (Producer)             (Lazy Adapter)       (Lazy Adapter)   (Eager Consumer)

Optimizing Pre-Allocation with size_hint

The optional size_hint(&self) -> (usize, Option<usize>) method returns a (lower_bound, upper_bound) pair on the remaining length. Overriding size_hint on custom bounded iterators allows collect::<Vec<_>>() to pre-allocate the exact buffer capacity in a single heap allocation.