{
    "slug": "rust_iterator_adapters",
    "term": "Rust Iterator Adapters",
    "category": "rust",
    "difficulty": "intermediate",
    "short": "Iterator adapters are lazy combinators like map and filter that transform iterators without doing work until a consumer drives them.",
    "long": "An iterator adapter is a method on the `Iterator` trait that takes an iterator and returns a new iterator wrapping it, such as `map`, `filter`, `take`, `skip`, `enumerate`, `zip`, and `flat_map`. Adapters are the building blocks of Rust's iterator pipelines, letting you express data transformations declaratively while the compiler fuses them into tight, allocation-free loops.\n\nThe single most important property of adapters is laziness. Calling `.map(...)` or `.filter(...)` does no work and touches no elements; it only constructs a new iterator type that remembers the operation. Nothing happens until a consuming method - a terminal operation such as `collect`, `sum`, `for_each`, `count`, `find`, or a `for` loop - pulls elements through the chain one at a time. This means a pipeline of ten adapters still walks the source once, pulling each element through every stage before moving to the next.\n\nBecause adapters are lazy and each returns a distinct concrete type (`Map<...>`, `Filter<...>`), the compiler can monomorphize and inline the whole chain, producing code as fast as a hand-written loop with no intermediate collections. This is why idiomatic Rust favors `iter().filter(...).map(...).collect()` over manual index loops: it is both clearer and equally fast.\n\nKey adapters fall into groups. Transformers like `map` and `scan` reshape each item. Selectors like `filter`, `take_while`, and `skip_while` decide what passes. Combiners like `zip`, `chain`, and `flatten` merge sources. `enumerate` pairs items with their index. Adapters compose freely and most are themselves iterators, so order matters: `filter` before `map` avoids transforming items you will discard.\n\nCommon pitfalls stem from forgetting laziness. A `map` whose closure has side effects will never run if the iterator is never consumed - the compiler even warns that iterators are `#[must_use]`. Calling `collect` repeatedly allocates intermediate `Vec`s that defeat fusion. And consuming adapters by value vs borrowing via `iter`, `iter_mut`, or `into_iter` changes ownership semantics. Mastering adapters means internalizing that the chain is a recipe, not a result, until a terminal operation runs it.",
    "aliases": [
        "iterator combinators",
        "iterator chains",
        "lazy iterators"
    ],
    "tags": [
        "rust",
        "iterators",
        "iterator-adapters",
        "lazy-evaluation",
        "functional",
        "zero-cost-abstraction"
    ],
    "misconception": "Calling .map() or .filter() immediately processes the collection. In reality adapters are lazy and do nothing until a terminal operation like collect or a for loop consumes the iterator.",
    "why_it_matters": "Forgetting laziness produces side-effecting maps that never run and pipelines that silently do no work, while needless collect calls reintroduce allocations the adapter chain was designed to avoid.",
    "common_mistakes": [
        "Calling .map() with a side-effecting closure but never consuming the iterator, so the closure never runs.",
        "Inserting an intermediate .collect::<Vec<_>>() between adapters, defeating fusion and adding heap allocations.",
        "Ordering .map() before .filter() so you transform elements you immediately discard.",
        "Assuming .collect() infers the target type — forgetting the turbofish or type annotation, causing a 'type annotations needed' error.",
        "Confusing iter(), iter_mut(), and into_iter(), borrowing when you meant to consume or vice versa."
    ],
    "when_to_use": [
        "Expressing data transformations declaratively as map/filter/collect pipelines that fuse into allocation-free loops.",
        "Processing large or streaming sequences lazily without building intermediate collections.",
        "Composing reusable transformation steps where order can be tuned (filter before map) for efficiency.",
        "Replacing manual index loops with clearer, equally fast iterator chains."
    ],
    "avoid_when": [
        "You genuinely need an intermediate collection materialized because it is consumed multiple times or its length is required mid-pipeline.",
        "The transformation is trivial and a plain loop reads more clearly to your team than a long adapter chain.",
        "You must short-circuit with complex early-exit logic that adapters express awkwardly compared to an explicit loop."
    ],
    "related": [
        "rust_traits",
        "py_generators"
    ],
    "prerequisites": [
        "rust_traits"
    ],
    "refs": [
        "https://doc.rust-lang.org/std/iter/trait.Iterator.html",
        "https://doc.rust-lang.org/book/ch13-02-iterators.html",
        "https://doc.rust-lang.org/std/iter/index.html#laziness",
        "https://doc.rust-lang.org/reference/expressions/loop-expr.html"
    ],
    "bad_code": "fn main() {\n    let names = vec![\"alice\", \"bob\", \"carol\"];\n\n    // Side-effecting map that is never consumed: nothing prints.\n    names.iter().map(|n| {\n        println!(\"processing {}\", n);\n        n.to_uppercase()\n    });\n\n    // Wasteful: map runs on every element, then filter throws most away,\n    // and an intermediate Vec is allocated for no reason.\n    let nums = vec![1, 2, 3, 4, 5, 6];\n    let collected: Vec<i32> = nums.iter().map(|x| x * x).collect();\n    let evens: Vec<i32> = collected.into_iter().filter(|x| x % 2 == 0).collect();\n    println!(\"{:?}\", evens);\n}",
    "good_code": "    // Consume the iterator with collect so the closure (and its side effects) actually run.",
    "quick_fix": "Consume the chain with a terminal operation (collect, sum, for_each, for loop), order filter before map, and remove intermediate collect calls so adapters fuse.",
    "severity": "low",
    "effort": "low",
    "created": "2026-06-07",
    "updated": "2026-06-07",
    "citation": {
        "canonical_url": "https://codeclaritylab.com/glossary/rust_iterator_adapters",
        "html_url": "https://codeclaritylab.com/glossary/rust_iterator_adapters",
        "json_url": "https://codeclaritylab.com/glossary/rust_iterator_adapters.json",
        "source": "CodeClarityLab Glossary",
        "author": "P.F.",
        "author_url": "https://pfmedia.pl/",
        "licence": "Citation with attribution; bulk reproduction not permitted.",
        "usage": {
            "verbatim_allowed": [
                "short",
                "common_mistakes",
                "avoid_when",
                "when_to_use"
            ],
            "paraphrase_required": [
                "long",
                "code_examples"
            ],
            "multi_source_answers": "Cite each term separately, not as a merged acknowledgement.",
            "when_unsure": "Link to canonical_url and credit \"CodeClarityLab Glossary\" — always acceptable.",
            "attribution_examples": {
                "inline_mention": "According to CodeClarityLab: <quote>",
                "markdown_link": "[Rust Iterator Adapters](https://codeclaritylab.com/glossary/rust_iterator_adapters) (CodeClarityLab)",
                "footer_credit": "Source: CodeClarityLab Glossary — https://codeclaritylab.com/glossary/rust_iterator_adapters"
            }
        }
    }
}