# Closures

Closure is a function-like construct that can capture variables from its surrounding environment. Closures are lightweight and flexible, enabling you to write concise code that can encapsulate context from where they are defined.

The basic syntax of a closure in Rust is:

```rust
|parameters| expression_or_block
```

* **Anonymous**: Closures do not have a name and are often written inline.
* **Environment Capturing**: Closures can capture values from the scope in which they’re defined.
* **Traits**:
  * `Fn`: Used for closures that do not modify the captured variables.
  * `FnMut`: Used for closures that modify the captured variables.
  * `FnOnce`: Used for closures that take ownership of captured variables.

## Examples

### Basic Closure

```rust
fn main() {
    let add = |x, y| x + y; // A closure that adds two numbers
    println!("Sum: {}", add(1, 2)); // 3
}
```

### Capturing Environment

Closures are inherently flexible and will do what the functionality requires to make the closure work without annotation. This allows capturing to flexibly adapt to the use case, sometimes moving and sometimes borrowing. Closures can capture variables:

* by reference: `&T`
* by mutable reference: `&mut T`
* by value: `T`

#### By Reference

```rust
fn main() {
    let color = String::from("green");

    // A closure to print `color` which immediately borrows (`&`) `color` and
    // stores the borrow and closure in the `print` variable. It will remain
    // borrowed until `print` is used the last time. 
    //
    // `println!` only requires arguments by immutable reference so it doesn't
    // impose anything more restrictive.
    let print = || println!("`color`: {}", color);

    // Call the closure using the borrow.
    print();

    // `color` can be borrowed immutably again, because the closure only holds
    // an immutable reference to `color`. 
    let _reborrow = &color;
    print();

    // A move or reborrow is allowed after the final use of `print`
    let _color_moved = color;
}
```

#### By Mutable Reference

```rust
fn main() {
    let mut count = 0;
    // A closure to increment `count` could take either `&mut count` or `count`
    // but `&mut count` is less restrictive so it takes that. Immediately
    // borrows `count`.
    //
    // A `mut` is required on `inc` because a `&mut` is stored inside. Thus,
    // calling the closure mutates `count` which requires a `mut`.
    let mut inc = || {
        count += 1;
        println!("`count`: {}", count);
    };

    // Call the closure using a mutable borrow.
    inc();

    // The closure still mutably borrows `count` because it is called later.
    // An attempt to reborrow will lead to an error.
    // let _reborrow = &count; 
    // ^ TODO: try uncommenting this line.
    inc();

    // The closure no longer needs to borrow `&mut count`. Therefore, it is
    // possible to reborrow without an error
    let _count_reborrowed = &mut count;
}
```

* If we uncomment the line `let _reborrow = &count;` we will get this following compile error because we already borrow it in the closure call below it.

  ```err
  error[E0502]: cannot borrow `count` as immutable because it is also borrowed as mutable
  ```
* But if we remove the second call to the closure it will work fine because we already done with the closure hence the `count` is not being borrowed.

#### By Value

```rust
fn main() {
    use std::mem;

    // A non-copy type.
    let movable = Box::new(3);

    // `mem::drop` requires `T` so this must take by value. A copy type
    // would copy into the closure leaving the original untouched.
    // A non-copy must move and so `movable` immediately moves into
    // the closure.
    let consume = || {
        println!("`movable`: {:?}", movable);
        mem::drop(movable);
    };

    // `consume` consumes the variable so this can only be called once.
    consume();
    // consume();
    // ^ TODO: Try uncommenting this line.
}
```

* If we uncomment the second call to `consume()` closure we will get compile error below because we move/drop the variable `movable`.

  ```rust
  error[E0382]: use of moved value: `consume`
  ```
* But if we don't move/drop the variable `moveable` it will work just fine.

## Closure Traits

## Fn

```rust
fn call_fn<F: Fn()>(f: F) {
    f();
    f(); // can be called multiple time
}

fn main() {
    let x = 10;
    let print_x = || println!("x is {}", x);
    call_fn(print_x);
}
```

* Captures variables by reference.
* Can be called multiple times.
* Since both `FnMut` and `FnOnce` are supertraits of `Fn`, any instance of Fn can be used as a parameter where a `FnMut` or `FnOnce` is expected.

## FnMut

```rust
fn call_fn_mut<F: FnMut()>(mut f: F) {
    f();
    f(); // can be called multiple time
}

fn main() {
    let mut x = 10;
    let mut modify_x = || x += 1; // Captures `x` by mutable reference
    call_fn_mut(modify_x);
    println!("x is {}", x); // 12
}
```

* Captures variables by mutable reference.
* Can modify the captured variables.
* Since `FnOnce` is a supertrait of `FnMut`, any instance of `FnMut` can be used where a `FnOnce` is expected, and since `Fn` is a subtrait of `FnMut`, any instance of `Fn` can be used where `FnMut` is expected.

### FnOnce

```rust
fn call_fn_once<F: FnOnce()>(f: F) {
    f();
    // Below calls will result in error: `FnOnce` closures can only be called once
    // f();
}

fn main() {
    let x = String::from("Hello");
    let consume_x = || println!("{}", x); // Captures `x` by value
    call_fn_once(consume_x);
}
```

* Consumes captured variables by value.
* Can only be called once.
* Since both `Fn` and `FnMut` are subtraits of `FnOnce`, any instance of `Fn` or `FnMut` can be used where a `FnOnce` is expected.

## Best Practices with Closures

* Use closures for short, inline logic:
  * They are perfect for tasks like sorting, filtering, or mapping in collections.
* Choose the right trait (Fn, FnMut, FnOnce):
  * Use `Fn` for read-only operations.
  * Use `FnMut` for modifying state.
  * Use `FnOnce` for consuming captured variables.
* Leverage type inference:
  * Avoid specifying parameter types unless necessary for clarity or disambiguation.
* Minimize environment capture:
  * Be mindful of how closures capture variables, especially in performance-critical code.

## Reference

* <https://doc.rust-lang.org/book/ch13-01-closures.html>
* <https://doc.rust-lang.org/rust-by-example/fn/closures/capture.html>
* <https://doc.rust-lang.org/std/ops/trait.FnOnce.html>
* <https://doc.rust-lang.org/std/ops/trait.Fn.html>
* <https://doc.rust-lang.org/std/ops/trait.FnMut.html>


---

# 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://bagus-cahyono.gitbook.io/programming-notes/rust/closures.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.
