Closure expressions - The Rust Reference

## Keyboard shortcuts

Press `←` or `→` to navigate between chapters

Press `S` or `/` to search in the book

Press `?` to show this help

Press `Esc` to hide this help

[expr.closure]

# Closure expressions

[expr.closure.syntax]

Syntax
ClosureExpression →
async?​1
move?
( || | | ClosureParameters? | )
( Expression | -> TypeNoBounds BlockExpression )

ClosureParameters → ClosureParam ( , ClosureParam )* ,?

ClosureParam → OuterAttribute* PatternNoTopAlt ( : Type )?

[expr.closure.intro]

A closure expression, also known as a lambda expression or a lambda, defines a closure type and evaluates to a value of that type. The syntax for a closure expression is an optional `async` keyword, an optional `move` keyword, then a pipe-symbol-delimited (`|`) comma-separated list of patterns, called the closure parameters each optionally followed by a `:` and a type, then an optional `->` and type, called the return type, and then an expression, called the closure body operand.

[expr.closure.param-type]

The optional type after each pattern is a type annotation for the pattern.

[expr.closure.explicit-type-body]

If there is a return type, the closure body must be a block.

[expr.closure.parameter-restriction]

A closure expression denotes a function that maps a list of parameters onto the expression that follows the parameters. Just like a `let` binding, the closure parameters are irrefutable patterns, whose type annotation is optional and will be inferred from context if not given.

[expr.closure.unique-type]

Each closure expression has a unique, anonymous type.

[expr.closure.captures]

Significantly, closure expressions capture their environment, which regular function definitions do not.

[expr.closure.capture-inference]

Without the `move` keyword, the closure expression infers how it captures each variable from its environment, preferring to capture by shared reference, effectively borrowing all outer variables mentioned inside the closure’s body.

[expr.closure.capture-mut-ref]

If needed the compiler will infer that instead mutable references should be taken, or that the values should be moved or copied (depending on their type) from the environment.

[expr.closure.capture-move]

A closure can be forced to capture its environment by copying or moving values by prefixing it with the `move` keyword. This is often used to ensure that the closure’s lifetime is `'static`.

[expr.closure.trait-impl]

## Closure trait implementations

Which traits the closure type implement depends on how variables are captured, the types of the captured variables, and the presence of `async`. See the call traits and coercions chapter for how and when a closure implements `Fn`, `FnMut`, and `FnOnce`. The closure type implements `Send` and `Sync` if the type of every captured variable also implements the trait.

[expr.closure.async]

## Async closures

[expr.closure.async.intro]

Closures marked with the `async` keyword indicate that they are asynchronous in an analogous way to an async function.

[expr.closure.async.future]

Calling the async closure does not perform any work, but instead evaluates to a value that implements `Future` that corresponds to the computation of the body of the closure.

    #![allow(unused)]
    fn main() {
    async fn takes_async_callback(f: impl AsyncFn(u64)) {
        f(0).await;
        f(1).await;
    }

    async fn example() {
        takes_async_callback(async |i| {
            core::future::ready(i).await;
            println!("done with {i}.");
        }).await;
    }
    }

[expr.closure.async.edition2018]

> 2018 Edition differences

> Async closures are only available beginning with Rust 2018.

## Example

In this example, we define a function `ten_times` that takes a higher-order function argument, and we then call it with a closure expression as an argument, followed by a closure expression that moves values from its environment.

    #![allow(unused)]
    fn main() {
    fn ten_times<F>(f: F) where F: Fn(i32) {
        for index in 0..10 {
            f(index);
        }
    }

    ten_times(|j| println!("hello, {}", j));
    // With type annotations
    ten_times(|j: i32| -> () { println!("hello, {}", j) });

    let word = "konnichiwa".to_owned();
    ten_times(move |j| println!("{}, {}", word, j));
    }

## Attributes on closure parameters

[expr.closure.param-attributes]

Attributes on closure parameters follow the same rules and restrictions as regular function parameters.

1. The `async` qualifier is not allowed in the 2015 edition. ↩