# Closures & Iterators

## Closures

### What is Closure?

{% hint style="success" %}
💡 Closures in Rust are anonymous functions that capture and use variables from their enclosing scope. They are often referred to as *lambda expressions* or *anonymous functions* in other programming languages.
{% endhint %}

{% hint style="success" %}
💡 Rust’s closures allow you to store them in variables, pass them as arguments to other functions, and return them from functions. Furthermore, you can create closures in one place and then call them elsewhere to evaluate them in different contexts.
{% endhint %}

Closures in Rust are defined using vertical bars `|` to enclose their parameters, followed by the body of the closure:

```rust
let closure = |param1, param2| {
    // closure body
};
```

```rust
fn main() {
    let my_closure = |x: i32| -> i32 { x + 1 };

    let x = my_closure(12);
    println!("x: {x}") // x: 13
}
```

In this example, we define a closure which is called `my_closure`. This closure includes:

* `|x: i32|`: This part establishes the closure's parameters. `x` is the parameter name and `i32` is its type.
* `> i32`: This specifies the return type of the closure.
* `x + 1`: This is the closure's body.

We call the closure with the `x` parameter of `12`. The result should be `12 + 1 = 13`.

This example also illustrates that a variable can bind to a closure definition, and we can later call the closure by using the variable name and parentheses (`my_closure()`) similar to when we call a function.

### Capturing References or Moving Ownership

Closures can capture variables from their environment (enclosing scope) in three ways:

1. **By reference (immutable):** The closure borrows the variable immutably.
2. **By reference (mutable):** The closure borrows the variable mutably.
3. **By value:** The closure takes ownership of the variable.

```rust
fn main() {
    let num: i32 = 5;

    // Capture num by reference (immutable)
    let add_one_v1 = |x: i32| x + num;

    // Capture num by reference (mutable)
    let add_one_v2 = |mut x: i32| {
        x += num;
        x
    };

    let result_v1 = add_one_v1(5);
    let result_v2 = add_one_v2(5);

    println!("result_v1: {result_v1}\\nresult_v2: {result_v2}")
}

// Output
result_v1: 10
result_v2: 10
```

```rust
fn main() {
    // Moving ownership
    let list = vec![1, 2, 3];
    let closure = move || println!("{:?}", list);

    closure(); // [1, 2, 3]

    // `list` is no longer accessible here as it has been moved into the closure.
    // Uncomment to see the error
    // println!("list: {list:?}");
}
```

### Closure Type Inference and Annotation

{% hint style="info" %}
Closures in Rust typically do not require type annotations for their parameters or return values, unlike `fn` functions. This is because closures are used within a narrow context, and the compiler can usually infer their types.
{% endhint %}

Type annotations are necessary for functions because they define an explicit interface, ensuring that all users agree on the types of values a function uses and returns. However, closures are usually short-lived and used in specific, limited contexts, making type inference sufficient in most cases.

In some situations, you may choose to add type annotations to closures for clarity and explicitness, even though it increases verbosity.

There are some variants of the closure syntax:

```rust
fn main() {
    // fully annotated closure definition
    let fully_annotated_closure = |x: i32| -> i32 { x + 1 };

    // Remove the type annotations from the closure definition
    // and remove the curly brackets,
    // which are optional because the closure body has only one expression
    let type_annotations_closure = |x| x + 1;

    // multiple parameters
    let multiple_parameters_closure = |x: i32, y: i32| x + y;

    let x = fully_annotated_closure(12);
    let y = type_annotations_closure(12);
    let z = multiple_parameters_closure(5, 5);

    println!("x: {x}, y: {y}, z: {z}")
}
```

### Moving Captured Values Out of `Closures` and the `Fn` Traits

{% hint style="success" %}
💡 Once a closure captures a reference or takes ownership of a value from its defining environment, the code within the closure's body determines how these references or values are used when the closure is executed. This influences what, if anything, is moved into or out of the closure during its execution.
{% endhint %}

{% hint style="success" %}
💡 A closure body can perform various actions: it can move a captured value out of the closure, mutate the captured value, leave the value unchanged, or not capture anything from the environment at all.
{% endhint %}

Rust offers three closure traits to distinguish how captured values are handled:

* **`FnOnce`**: This is the base trait for all closures. It indicates that the closure can be called only once. If the closure moves captured values, it will only implement `FnOnce` and not the other traits.
* **`FnMut`**: This trait is implemented for closures that don't move captured values out of their body but might mutate them. This allows the closure to be called multiple times with side effects.
* **`Fn`**: This trait is for closures that don’t move or mutate captured values. They can be called multiple times without affecting the captured environment

> Functions can also implement all three of the `Fn` traits. If we don't need to capture a value from the environment, we can use a function name instead of a closure in contexts that require an implementation of one of the `Fn` traits.

#### `Fn` Trait

```rust
fn call_fn<F>(closure: F)
where
    F: Fn(i32) -> i32,
{
    println!("Result: {}", closure(5));
}

fn main() {
    let x = 10;
    let closure = |y| y + x;
    call_fn(closure); // Outputs: Result: 15

    // We can call it multiple times without affecting the captured environment
    call_fn(closure); // Outputs: Result: 15
}
```

#### `FnMut` Trait

```rust
fn call_fn_mut<F>(mut closure: F)
where
    F: FnMut(i32) -> i32,
{
    println!("Result: {}", closure(5));
    println!("Result: {}", closure(10));
}

fn main() {
    let mut x = 10;
    let closure = |y| {
        x += y; // `x` is captured by mutable reference
        x
    };
    
    call_fn_mut(closure); // Outputs: Result: 15, Result: 25
    println!("x after call_fn_mut: {}", x); // x has been mutated, outputs: 25
}

```

#### `FnOnce` Trait

```rust
fn call_fn_once<F>(closure: F)
where
    F: FnOnce(String) -> String,
{
    let result = closure(String::from(", world!"));
    println!("Result: {}", result);
}

fn main() {
    let x = String::from("Hello");
    let closure = move |y: String| x + &y; // `x` is captured by taking ownership

    call_fn_once(closure); // Outputs: Result: Hello, world!

    // println!("x after call_fn_once: {}", x) // `x` is no longer accessible here as it has been moved into the closure
}
```

## Iterators

### What is an Iterator?

{% hint style="success" %}
&#x20;💡 The [**Iterator**](https://doc.rust-lang.org/nightly/std/iter/trait.Iterator.html) is a trait that allows you to sequentially access the elements of a collection or sequence. It provides a way to process a sequence of elements, one element at a time, and allows us to apply operations such as ***mapping***, ***filtering***, and ***folding*** over the sequence.
{% endhint %}

Rust provides several iterator traits to handle different scenarios:

* **`Iterator`**: The base trait for all iterators. It defines the `next()` method to retrieve the next element.
* **`IntoIterator`**: Allows converting a value into an iterator.
* **`FromIterator`**: Allows creating a collection from an iterator.

For example, Rust provides a convenient way to iterate over iterators using the `for` loop:

```rust
fn main() {
    let v = vec![1, 2, 3, 4, 5];
    for x in &v {
        println!("value: {}", x);
    }
}

// Output
value: 1
value: 2
value: 3
value: 4
value: 5
```

{% hint style="success" %}
&#x20;💡 Iterators are **lazy**, meaning that they don’t perform any work until they are consumed such as by `for` loop or `collect` method. Once an iterator is consumed, it can’t be used again, meaning that you can’t reuse it to iterate over the same element again.
{% endhint %}

```rust
fn main() {
    let v = vec![1, 2, 3];
    let mut iter = v.iter();

    // First iteration
    while let Some(x) = iter.next() {
        println!("value: {}", x);
    }

    // Second iteration (will not print anything)
    while let Some(x) = iter.next() {
        println!("value: {}", x);
    }
}
```

In this example, the first `while` loop consumes the iterator by iterating over all elements.

The second `while` loop tries to iterate again but immediately exits because the iterator is empty.

### The `Iterator` Trait

{% hint style="info" %}
💡 The `Iterator` trait in Rust defines a sequence of elements and a way to iterate over them.
{% endhint %}

* **`Item`** is the associated type that represents the type of elements the iterator will produce.
* **`next`** is the core method of the `Iterator` trait. It advances the iterator and returns the next item in the sequence wrapped in an `Option`. If there are no more items, it returns `None`.

```rust
pub trait Iterator {
    type Item;

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

    // other methods
}
```

Many collections in Rust, like **arrays**, **vectors**, and **ranges**, implement the `Iterator` trait, allowing you to create iterators from them.

You can manually use the `next()` method to iterate over each element of the iterator at a time.

```rust
fn main() {
    let v = vec![1, 2, 3];
    let mut iter = v.iter();

    println!("Value: {:?}", iter.next()); // Some(1)
    println!("Value: {:?}", iter.next()); // Some(2)
    println!("Value: {:?}", iter.next()); // Some(3)
    println!("Value: {:?}", iter.next()); // None
}
```

Each time we call `next` method, it consumes an element from the iterator. We didn’t need to make `iter` mutable when we used a `for` loop because the loop took ownership of `iter` and made it mutable behind the scenes.

> It's important to note that the values returned by the `next` method are immutable references to the elements in the vector. This is because the `iter` method creates an iterator that yields immutable references.

### Consuming Iterators

{% hint style="success" %}
💡 Methods that call [**`next`**](https://doc.rust-lang.org/beta/std/iter/trait.Iterator.html#tymethod.next) are known as ***consuming adapters*** because they will consume the iterator and produce a final value.

Essentially, each time you call one of these methods, you're advancing through the iterator and consuming its elements one at a time. Once an element is consumed, it's gone, and the iterator moves on to the next one.
{% endhint %}

Some of the common methods that consume the iterator such as: `collect()`, `sum()`, `for_each()`, etc.

#### The `collect` method

{% hint style="info" %}
&#x20;💡 The [**`collect`**](https://doc.rust-lang.org/beta/std/iter/trait.Iterator.html#method.collect) method converts an iterator into a collection, like a `Vec`, `HashMap`, or other types that implement `FromIterator`.
{% endhint %}

In this example, we’re calling the `map` method and applying the closure `|x| x * 2` to each element and doubling each number.

After that, we call the `collect` method to consume the iterator and collect its element into a new vector named `doubled`.

```rust
fn main() {
    let v = vec![1, 2, 3];
    let doubled: Vec<i32> = v.iter().map(|x| x * 2).collect();

    println!("After doubled: {:?}", doubled); // After doubled: [2, 4, 6]
}
```

#### The `sum` method

{% hint style="info" %}
💡 The [**`sum`**](https://doc.rust-lang.org/beta/std/iter/trait.Iterator.html#method.sum) method consumes the iterator and returns the sum of the elements.
{% endhint %}

In this example, we’re using the `sum` method to iterate over each element and accumulate the sum of each element in the vector.

```rust
fn main() {
    let v = vec![1, 2, 3];
    let total: i32 = v.iter().sum();

    println!("Total sum: {:?}", total); // Total sum: 6
}
```

#### The `for_each` method

{% hint style="info" %}
💡 The [**`for_each`**](https://doc.rust-lang.org/beta/std/iter/trait.Iterator.html#method.for_each) method applies a function to each element of the iterator.
{% endhint %}

In this example, we’re using the `for_each` method to iterate over each element and print out each element in the vector.

```rust
fn main() {
    let v = vec![1, 2, 3];
    v.iter().for_each(|x| println!("{}", x));

    // Output: 1 2 3
}
```

### Producing Iterators

{% hint style="success" %}
💡 **Iterator adapter** is a method provided by the `Iterator` trait that transforms one iterator into another iterator. These adapters produce new iterators that can be further chained, filtered, or modified without consuming the original iterator or producing a final value immediately. This process is also known as **lazy evaluation**.
{% endhint %}

Some of the common methods that produce the iterator such as: `map()`, `filter()`, `enumerate()`, `take()`, `skip()`, etc.

#### The `map` method

{% hint style="info" %}
&#x20;💡 We can use [**`map`**](https://doc.rust-lang.org/beta/std/iter/trait.Iterator.html#method.map) method to transform each element of an iterator using a custom function that is passed in the map as an argument.
{% endhint %}

In this example, we’re using the `map` method to produce a new iterator that multiplies each element by 2.

```rust
fn main() {
    let v = vec![1, 2, 3];
    let after_mapping = v.iter().map(|x| x * 2);

    println!("after_mapping: {:?}", after_mapping.collect::<Vec<_>>())
}

// Output: after_mapping: [2, 4, 6]
```

#### The `filter` method

{% hint style="info" %}
&#x20;💡 The [**`filter`**](https://doc.rust-lang.org/beta/std/iter/trait.Iterator.html#method.filter) produces a new iterator that includes only the elements that satisfy a given predicate.
{% endhint %}

In this example, we’re using the `filter` method to produce a new iterator that only contains even numbers.

```rust
fn main() {
    let v = vec![1, 2, 3, 4];
    let after_filtered = v.iter().filter(|&x| x % 2 == 0);

    println!("after_filtered: {:?}", after_filtered.collect::<Vec<_>>())
}

// Output: after_filtered: [2, 4]
```

#### The `enumerate` method

{% hint style="info" %}
💡 The [**`enumerate`**](https://doc.rust-lang.org/beta/std/iter/trait.Iterator.html#method.enumerate) method produces an iterator of pairs, where each pair contains the `index` and the `value` of the element.
{% endhint %}

In this example, we’re using the `enumerate` method to produce an iterator that yields `(index, value)` pairs.

```rust
fn main() {
    let v = vec!["a", "b", "c"];
    let after_enumerated = v.iter().enumerate();

    println!(
        "after_enumerated: {:?}",
        after_enumerated.collect::<Vec<_>>()
    )
}

// Output: after_enumerated: [(0, "a"), (1, "b"), (2, "c")]
```

#### The `take` method

{% hint style="info" %}
&#x20;💡 The [**`take`**](https://doc.rust-lang.org/beta/std/iter/trait.Iterator.html#method.take) method produces an iterator that yields only the first `n` elements of the original iterator.
{% endhint %}

In this example, we’re using the `take` method to produce an iterator that returns only the first 3 elements.

```rust
fn main() {
    let v = vec![1, 2, 3, 4, 5];
    let after_taken = v.iter().take(3);

    println!("after_taken: {:?}", after_taken.collect::<Vec<_>>())
}

// Output: after_taken: [1, 2, 3]
```

#### The `skip` method

{% hint style="info" %}
&#x20;💡 The [**`skip`**](https://doc.rust-lang.org/beta/std/iter/trait.Iterator.html#method.skip) method produces an iterator that skips the first `n` elements and yields the rest.
{% endhint %}

In this example, we’re using the `skip` method to produce an iterator that skips the first two elements and returns the rest.

```rust
fn main() {
    let v = vec![1, 2, 3, 4, 5];
    let after_skipped = v.iter().skip(2);

    println!("after_skipped: {:?}", after_skipped.collect::<Vec<_>>())
}

// Output: after_skipped: [3, 4, 5]
```

#### Chaining Producing Adapters

{% hint style="info" %}
💡 The powerful feature of producing an adapter is that it allows us to combine multiple iterator adapters to create a complex data transformation. This process is called **chaining-producing adapters**.
{% endhint %}

{% hint style="info" %}
&#x20;💡 By chaining these adapters, you can perform multiple operations on a data stream without creating intermediate collections.
{% endhint %}

Let’s see an example of chaining multiple producing adapters by combining all of the methods that we’ve been through in the previous section.

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

    // Chaining producing adapters
    let result: Vec<i32> = v
        .iter()
        .filter(|&&x| x % 2 == 0) // Keep only even numbers
        .map(|&x| x * 10)         // Multiply each by 10
        .take(2)                  // Take only the first 2 elements
        .collect();               // Collect the results into a vector

    println!("{:?}", result);     // Outputs: [20, 40]
}
```

We create a vector named `v` which contains numbers from **1** to **6**.

We call the `iter()` method on the vector `v`, creating an iterator over its elements. This iterator yields references to the elements of the vector.

In the first stage, we want to filter out to keep only even numbers. The `filter` method is applied to the iterator, creating a new iterator that yields only the elements that satisfy the given predicate, in this case is the even numbers.

In the second stage, we want to multiply each element by 10. The `map` method is applied to the filtered iterator, creating a new iterator that multiplies each element by 10.

In the third stage, we only want to take the first 2 elements from the previous result. The `take` method is applied to the iterator, creating a new iterator that yields at most 2 elements.

Finally, we call the `collect` method to consume the iterator and collect its elements into a new vector.

We can see that each adapter creates a new iterator, transforming the data in a specific way using the result produced by the previous method.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://thomasbui.gitbook.io/blog/software-engineering/rust-101/closures-and-iterators.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
