M Logo
๐Ÿ“ Rust for Beginners ยท Part 20 of 22

Rust Closures and Iterators Explained: map, filter, collect and sum

November 10, 2026

Welcome to episode 20 of Rust for Beginners, a series for complete beginners (no programming experience needed). In the last video, we learned about generics. Today, we'll learn closures and iterators, two tools that make Rust code short and clear. Every code block below is the exact code from the video, ready to copy.

1. New project

Let's create a new project called closures, and open it in VS Code.

bash
cargo new closures
cd closures

2. Closure

A closure is a small function without a name, that we can store in a variable. The parameters go between two vertical bars, and the body comes after.

src/main.rs:

rust
fn main() {
    let add_one = |x: i32| x + 1;
    println!("add_one(5) = {}", add_one(5));

    let tax = 0.2;
    let with_tax = |price: f64| price * (1.0 + tax);
    println!("100 with tax: {}", with_tax(100.0));
}

Output: add_one(5) = 6 / 100 with tax: 120

3. Call

We call it like any function: add one of five.

4. Capture

Unlike a normal function, a closure can use variables around it. with tax uses the tax variable from main. That's called capturing.

5. Run A

Let's run it. Six, and one hundred with tax is one hundred twenty.

bash
cargo run

6. Iterator

An iterator goes through items one by one. We get one from a vector with iter.

rust
fn main() {
    let numbers = vec![1, 2, 3, 4, 5];
    numbers.iter().map(|n| n * 2);
}

Warning, and no output:

text
warning: unused `Map` that must be used
 --> src/main.rs:3:5
  |
3 |     numbers.iter().map(|n| n * 2);
  |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  |
  = note: iterators are lazy and do nothing unless consumed
  = note: `#[warn(unused_must_use)]` (part of `#[warn(unused)]`) on by default
help: use `let _ = ...` to ignore the resulting value
  |
3 |     let _ = numbers.iter().map(|n| n * 2);
  |     +++++++

7. map

map runs a closure on every item. Here, it doubles each number. Let's run it.

bash
cargo run

8. Lazy

Nothing happened, and Rust warns us: iterators are lazy and do nothing unless consumed. map only describes the work.

9. collect

To run it, we consume the iterator. collect gathers the results into a new vector.

rust
fn main() {
    let numbers = vec![1, 2, 3, 4, 5];

    let doubled: Vec<i32> = numbers.iter().map(|n| n * 2).collect();
    println!("Doubled: {doubled:?}");

    let evens: Vec<&i32> = numbers.iter().filter(|n| *n % 2 == 0).collect();
    println!("Evens: {evens:?}");

    let total: i32 = numbers.iter().sum();
    println!("Total: {total}");
}

Output: Doubled: [2, 4, 6, 8, 10] / Evens: [2, 4] / Total: 15

10. filter, sum

filter keeps only the items where the closure returns true, here the even numbers. And sum adds everything up.

11. Run B

Let's run it.

bash
cargo run

12. Chain

We can chain steps together. Keep the words longer than four letters, make them uppercase, and collect. Each step on its own line reads like a recipe.

rust
fn main() {
    let words = vec!["apple", "fig", "banana", "kiwi", "cherry"];

    let long_words: Vec<String> = words
        .iter()
        .filter(|w| w.len() > 4)
        .map(|w| w.to_uppercase())
        .collect();
    println!("{long_words:?}");

    for (i, word) in words.iter().enumerate() {
        println!("{i}: {word}");
    }

    let sum_of_odd_squares: i32 = (1..=10).filter(|n| n % 2 == 1).map(|n| n * n).sum();
    println!("Sum of odd squares: {sum_of_odd_squares}");
}

Output:

text
["APPLE", "BANANA", "CHERRY"]
0: apple
1: fig
2: banana
3: kiwi
4: cherry
Sum of odd squares: 165

13. enumerate

enumerate gives each item together with its index.

14. Ranges

Ranges are iterators too. In one line: take one to ten, keep the odd numbers, square them, and add them up.

15. Run C

Let's run it.

bash
cargo run

Recap

To recap: a closure is an unnamed function that can capture its surroundings. Iterators are lazy. map and filter transform them, and collect, sum, or a for loop consume them.

16. `\

params\

src/main.rs:

rust
fn main() {
    let add_one = |x: i32| x + 1;
    println!("add_one(5) = {}", add_one(5));

    let tax = 0.2;
    let with_tax = |price: f64| price * (1.0 + tax);
    println!("100 with tax: {}", with_tax(100.0));
}

Output: add_one(5) = 6 / 100 with tax: 120

17. Recap: `\

x\

ยฉ 2026 All Rights Reserved By Mahmudul Alam