Iterators

fuse() and inspect()

The .fuse() and .inspect() adapters wrap an iterator without changing its yielded items: .fuse() guarantees that an iterator permanently yields None after its first None, and .inspect() runs a side-effecting closure on a shared reference to each item as it flows through a pipeline.

Ensuring Terminal Exhaustion with .fuse()

The Iterator trait contract does not strictly forbid a custom iterator from returning Some(x) again if .next() is called after an earlier call returned None. Wrapping an iterator in .fuse() returns a std::iter::Fuse<Self> (which implements the FusedIterator marker trait) that latches permanently on the first None and never polls the underlying iterator again:

struct FlakyAlternator {
    step: u8,
}

impl Iterator for FlakyAlternator {
    type Item = u8;

    fn next(&mut self) -> Option<Self::Item> {
        self.step += 1;
        // Returns None on even steps, but resumes returning Some on odd steps!
        if self.step % 2 == 1 {
            Some(self.step)
        } else {
            None
        }
    }
}

fn main() {
    let mut raw = FlakyAlternator { step: 0 };
    println!("Raw:   {:?}, {:?}, {:?}", raw.next(), raw.next(), raw.next());

    let mut fused = FlakyAlternator { step: 0 }.fuse();
    println!(
        "Fused: {:?}, {:?}, {:?}",
        fused.next(),
        fused.next(),
        fused.next()
    );
}
Raw:   Some(1), None, Some(3)
Fused: Some(1), None, None

Observing Pipeline Stages with .inspect()

The .inspect(f) adapter takes a closure FnMut(&Self::Item) and calls it with a shared reference &item before passing item unchanged to the next adapter. This makes .inspect() ideal for logging, debugging, or counting intermediate stages inside a multi-step iterator chain:

fn main() {
    let sum: i32 = [1, 2, 3, 4]
        .into_iter()
        .inspect(|x| println!("before filter: {x}"))
        .filter(|x| x % 2 == 0)
        .inspect(|x| println!("  after filter: {x}"))
        .map(|x| x * 10)
        .sum();

    println!("Total: {sum}");
}
before filter: 1
before filter: 2
  after filter: 2
before filter: 3
before filter: 4
  after filter: 4
Total: 60