|
1 | 1 | # Closure expressions
|
2 | 2 |
|
| 3 | +r[expr.closure] |
| 4 | + |
| 5 | +r[expr.closure.syntax] |
3 | 6 | > **<sup>Syntax</sup>**\
|
4 | 7 | > _ClosureExpression_ :\
|
5 | 8 | > `async`[^cl-async-edition]<sup>?</sup>\
|
|
15 | 18 | >
|
16 | 19 | > [^cl-async-edition]: The `async` qualifier is not allowed in the 2015 edition.
|
17 | 20 |
|
| 21 | +r[expr.closure.intro] |
18 | 22 | A *closure expression*, also known as a lambda expression or a lambda, defines a [closure type] and evaluates to a value of that type.
|
19 | 23 | 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*.
|
| 24 | + |
| 25 | +r[expr.closure.param-type] |
20 | 26 | The optional type after each pattern is a type annotation for the pattern.
|
| 27 | + |
| 28 | +r[expr.closure.explicit-type-body] |
21 | 29 | If there is a return type, the closure body must be a [block].
|
22 | 30 |
|
| 31 | +r[expr.closure.parameter-restriction] |
23 | 32 | A closure expression denotes a function that maps a list of parameters onto the expression that follows the parameters.
|
24 | 33 | 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.
|
| 34 | + |
| 35 | +r[expr.closure.unique-type] |
25 | 36 | Each closure expression has a unique, anonymous type.
|
26 | 37 |
|
| 38 | +r[expr.closure.captures] |
27 | 39 | Significantly, closure expressions _capture their environment_, which regular [function definitions] do not.
|
| 40 | + |
| 41 | +r[expr.closure.capture-inference] |
28 | 42 | Without the `move` keyword, the closure expression [infers how it captures each variable from its environment](../types/closure.md#capture-modes), preferring to capture by shared reference, effectively borrowing all outer variables mentioned inside the closure's body.
|
| 43 | + |
| 44 | +r[expr.closure.capture-mut-ref] |
29 | 45 | 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.
|
| 46 | + |
| 47 | +r[expr.closure.capture-move] |
30 | 48 | A closure can be forced to capture its environment by copying or moving values by prefixing it with the `move` keyword.
|
31 | 49 | This is often used to ensure that the closure's lifetime is `'static`.
|
32 | 50 |
|
33 | 51 | ## Closure trait implementations
|
34 | 52 |
|
| 53 | +r[expr.closure.trait-impl] |
| 54 | + |
35 | 55 | Which traits the closure type implement depends on how variables are captured, the types of the captured variables, and the presence of `async`.
|
36 | 56 | See the [call traits and coercions] chapter for how and when a closure implements `Fn`, `FnMut`, and `FnOnce`.
|
37 | 57 | The closure type implements [`Send`] and [`Sync`] if the type of every captured variable also implements the trait.
|
@@ -79,6 +99,8 @@ ten_times(move |j| println!("{}, {}", word, j));
|
79 | 99 |
|
80 | 100 | ## Attributes on closure parameters
|
81 | 101 |
|
| 102 | +r[expr.closure.param-attributes] |
| 103 | + |
82 | 104 | Attributes on closure parameters follow the same rules and restrictions as [regular function parameters].
|
83 | 105 |
|
84 | 106 | [_Expression_]: ../expressions.md
|
|
0 commit comments