# Iterators and Closures — Rust

Source: https://www.skillbyai.com/en/rust/c-iter

> map, filter, sum, collect.

## Lazy, composable, zero-cost

**Iterators** produce values one at a time; adapters such as `map`, `filter`, `take` and `enumerate` build lazy pipelines that run only when consumed by `sum`, `count`, `collect`, `max_by_key` or a for loop. **Closures** (`|o| o.amount > threshold`) capture variables from their environment. Iterator chains compile to code as fast as hand-written loops while being clearer. `iter()` borrows items, `into_iter()` takes ownership, `iter_mut()` borrows mutably.

## Processing orders with iterator chains, run

I ran this with Rust 1.99.0 (cargo run, edition 2024, standard library only). Paid orders sum to 3,057; names are collected into a Vec; max_by_key finds Meera's order; map applies a 10% discount; a closure captures the threshold; position finds the first unpaid order.

```rust
#[derive(Debug)]
struct Order { customer: &'static str, amount: u32, paid: bool }

fn main() {
    let orders = vec![
        Order { customer: "Asha", amount: 1259, paid: true },
        Order { customer: "Ravi", amount: 1200, paid: false },
        Order { customer: "Meera", amount: 1798, paid: true },
    ];
    let paid_total: u32 = orders.iter().filter(|o| o.paid).map(|o| o.amount).sum();
    let names: Vec<&str> = orders.iter().map(|o| o.customer).collect();
    let biggest = orders.iter().max_by_key(|o| o.amount).unwrap();
    let discounted: Vec<u32> = orders.iter().map(|o| o.amount * 90 / 100).collect();
    let threshold = 1250;                                   // closures capture variables
    let above = orders.iter().filter(|o| o.amount > threshold).count();
    println!("paid total {paid_total}");
    println!("{names:?} biggest={}", biggest.customer);
    println!("{discounted:?} above {threshold}: {above}");
    let first_unpaid = orders.iter().position(|o| !o.paid);
    println!("first unpaid index {first_unpaid:?}");
}
```

Output:

```
paid total 3057
["Asha", "Ravi", "Meera"] biggest=Meera
[1133, 1080, 1618] above 1250: 2
first unpaid index Some(1)
```

## Prefer iterators over index loops

Iterators avoid bounds checks and off-by-one errors; clippy even suggests them.

**Quiz:** When does a chain like iter().map(...).filter(...) actually run?

- [x] When it is consumed, for example by sum, collect or a for loop
- [ ] Immediately when map is called
- [ ] At compile time
- [ ] Never

*Answer:* When it is consumed, for example by sum, collect or a for loop. Iterators are lazy.
