]> git.proxmox.com Git - rustc.git/blob - src/doc/book/src/ch13-01-closures.md
New upstream version 1.63.0+dfsg1
[rustc.git] / src / doc / book / src / ch13-01-closures.md
1 <!-- Old heading. Do not remove or links may break. -->
2 <a id="closures-anonymous-functions-that-can-capture-their-environment"></a>
3
4 ## Closures: Anonymous Functions that Capture Their Environment
5
6 Rust’s closures are anonymous functions you can save in a variable or pass as
7 arguments to other functions. You can create the closure in one place and then
8 call the closure elsewhere to evaluate it in a different context. Unlike
9 functions, closures can capture values from the scope in which they’re defined.
10 We’ll demonstrate how these closure features allow for code reuse and behavior
11 customization.
12
13 <!-- Old headings. Do not remove or links may break. -->
14 <a id="creating-an-abstraction-of-behavior-with-closures"></a>
15 <a id="refactoring-using-functions"></a>
16 <a id="refactoring-with-closures-to-store-code"></a>
17
18 ### Capturing the Environment with Closures
19
20 We’ll first examine how we can use closures to capture values from the
21 environment they’re defined in for later use. Here’s the scenario: Every so
22 often, our t-shirt company gives away an exclusive, limited-edition shirt to
23 someone on our mailing list as a promotion. People on the mailing list can
24 optionally add their favorite color to their profile. If the person chosen for
25 a free shirt has their favorite color set, they get that color shirt. If the
26 person hasn’t specified a favorite color, they get whatever color the company
27 currently has the most of.
28
29 There are many ways to implement this. For this example, we’re going to use an
30 enum called `ShirtColor` that has the variants `Red` and `Blue` (limiting the
31 number of colors available for simplicity). We represent the company’s
32 inventory with an `Inventory` struct that has a field named `shirts` that
33 contains a `Vec<ShirtColor>` representing the shirt colors currently in stock.
34 The method `shirt_giveaway` defined on `Inventory` gets the optional shirt
35 color preference of the free shirt winner, and returns the shirt color the
36 person will get. This setup is shown in Listing 13-1:
37
38 <span class="filename">Filename: src/main.rs</span>
39
40 ```rust,noplayground
41 {{#rustdoc_include ../listings/ch13-functional-features/listing-13-01/src/main.rs}}
42 ```
43
44 <span class="caption">Listing 13-1: Shirt company giveaway situation</span>
45
46 The `store` defined in `main` has two blue shirts and one red shirt remaining
47 to distribute for this limited-edition promotion. We call the `giveaway` method
48 for a user with a preference for a red shirt and a user without any preference.
49
50 Again, this code could be implemented in many ways, and here, to focus on
51 closures, we’ve stuck to concepts you’ve already learned except for the body of
52 the `giveaway` method that uses a closure. In the `giveaway` method, we get the
53 user preference as a parameter of type `Option<ShirtColor>` and call the
54 `unwrap_or_else` method on `user_preference`. The [`unwrap_or_else` method on
55 `Option<T>`][unwrap-or-else]<!-- ignore --> is defined by the standard library.
56 It takes one argument: a closure without any arguments that returns a value `T`
57 (the same type stored in the `Some` variant of the `Option<T>`, in this case
58 `ShirtColor`). If the `Option<T>` is the `Some` variant, `unwrap_or_else`
59 returns the value from within the `Some`. If the `Option<T>` is the `None`
60 variant, `unwrap_or_else` calls the closure and returns the value returned by
61 the closure.
62
63 We specify the closure expression `|| self.most_stocked()` as the argument to
64 `unwrap_or_else`. This is a closure that takes no parameters itself (if the
65 closure had parameters, they would appear between the two vertical bars). The
66 body of the closure calls `self.most_stocked()`. We’re defining the closure
67 here, and the implementation of `unwrap_or_else` will evaluate the closure
68 later if the result is needed.
69
70 Running this code prints:
71
72 ```console
73 {{#include ../listings/ch13-functional-features/listing-13-01/output.txt}}
74 ```
75
76 One interesting aspect here is that we’ve passed a closure that calls
77 `self.most_stocked()` on the current `Inventory` instance. The standard library
78 didn’t need to know anything about the `Inventory` or `ShirtColor` types we
79 defined, or the logic we want to use in this scenario. The closure captures an
80 immutable reference to the `self` `Inventory` instance and passes it with the
81 code we specify to the `unwrap_or_else` method. Functions, on the other hand,
82 are not able to capture their environment in this way.
83
84 ### Closure Type Inference and Annotation
85
86 There are more differences between functions and closures. Closures don’t
87 usually require you to annotate the types of the parameters or the return value
88 like `fn` functions do. Type annotations are required on functions because the
89 types are part of an explicit interface exposed to your users. Defining this
90 interface rigidly is important for ensuring that everyone agrees on what types
91 of values a function uses and returns. Closures, on the other hand, aren’t used
92 in an exposed interface like this: they’re stored in variables and used without
93 naming them and exposing them to users of our library.
94
95 Closures are typically short and relevant only within a narrow context rather
96 than in any arbitrary scenario. Within these limited contexts, the compiler can
97 infer the types of the parameters and the return type, similar to how it’s able
98 to infer the types of most variables (there are rare cases where the compiler
99 needs closure type annotations too).
100
101 As with variables, we can add type annotations if we want to increase
102 explicitness and clarity at the cost of being more verbose than is strictly
103 necessary. Annotating the types for a closure would look like the definition
104 shown in Listing 13-2. In this example, we’re defining a closure and storing it
105 in a variable rather than defining the closure in the spot we pass it as an
106 argument as we did in Listing 13-1.
107
108 <span class="filename">Filename: src/main.rs</span>
109
110 ```rust
111 {{#rustdoc_include ../listings/ch13-functional-features/listing-13-02/src/main.rs:here}}
112 ```
113
114 <span class="caption">Listing 13-2: Adding optional type annotations of the
115 parameter and return value types in the closure</span>
116
117 With type annotations added, the syntax of closures looks more similar to the
118 syntax of functions. Here we define a function that adds 1 to its parameter and
119 a closure that has the same behavior, for comparison. We’ve added some spaces
120 to line up the relevant parts. This illustrates how closure syntax is similar
121 to function syntax except for the use of pipes and the amount of syntax that is
122 optional:
123
124 ```rust,ignore
125 fn add_one_v1 (x: u32) -> u32 { x + 1 }
126 let add_one_v2 = |x: u32| -> u32 { x + 1 };
127 let add_one_v3 = |x| { x + 1 };
128 let add_one_v4 = |x| x + 1 ;
129 ```
130
131 The first line shows a function definition, and the second line shows a fully
132 annotated closure definition. In the third line, we remove the type annotations
133 from the closure definition. In the fourth line, we remove the brackets, which
134 are optional because the closure body has only one expression. These are all
135 valid definitions that will produce the same behavior when they’re called.
136 Evaluating the closures is required for `add_one_v3` and `add_one_v4` to be
137 able to compile because the types will be inferred from their usage. This is
138 similar to `let v = Vec::new();` needing either type annotations or values of
139 some type to be inserted into the `Vec` for Rust to be able to infer the type.
140
141 For closure definitions, the compiler will infer one concrete type for each of
142 their parameters and for their return value. For instance, Listing 13-3 shows
143 the definition of a short closure that just returns the value it receives as a
144 parameter. This closure isn’t very useful except for the purposes of this
145 example. Note that we haven’t added any type annotations to the definition.
146 Because there are no type annotations, we can call the closure with any type,
147 which we’ve done here with `String` the first time. If we then try to call
148 `example_closure` with an integer, we’ll get an error.
149
150 <span class="filename">Filename: src/main.rs</span>
151
152 ```rust,ignore,does_not_compile
153 {{#rustdoc_include ../listings/ch13-functional-features/listing-13-03/src/main.rs:here}}
154 ```
155
156 <span class="caption">Listing 13-3: Attempting to call a closure whose types
157 are inferred with two different types</span>
158
159 The compiler gives us this error:
160
161 ```console
162 {{#include ../listings/ch13-functional-features/listing-13-03/output.txt}}
163 ```
164
165 The first time we call `example_closure` with the `String` value, the compiler
166 infers the type of `x` and the return type of the closure to be `String`. Those
167 types are then locked into the closure in `example_closure`, and we get a type
168 error when we next try to use a different type with the same closure.
169
170 ### Capturing References or Moving Ownership
171
172 Closures can capture values from their environment in three ways, which
173 directly map to the three ways a function can take a parameter: borrowing
174 immutably, borrowing mutably, and taking ownership. The closure will decide
175 which of these to use based on what the body of the function does with the
176 captured values.
177
178 In Listing 13-4, we define a closure that captures an immutable reference to
179 the vector named `list` because it only needs an immutable reference to print
180 the value:
181
182 <span class="filename">Filename: src/main.rs</span>
183
184 ```rust
185 {{#rustdoc_include ../listings/ch13-functional-features/listing-13-04/src/main.rs}}
186 ```
187
188 <span class="caption">Listing 13-4: Defining and calling a closure that
189 captures an immutable reference</span>
190
191 This example also illustrates that a variable can bind to a closure definition,
192 and we can later call the closure by using the variable name and parentheses as
193 if the variable name were a function name.
194
195 Because we can have multiple immutable references to `list` at the same time,
196 `list` is still accessible from the code before the closure definition, after
197 the closure definition but before the closure is called, and after the closure
198 is called. This code compiles, runs, and prints:
199
200 ```console
201 {{#include ../listings/ch13-functional-features/listing-13-04/output.txt}}
202 ```
203
204 Next, in Listing 13-5, we change the closure body so that it adds an element to
205 the `list` vector. The closure now captures a mutable reference:
206
207 <span class="filename">Filename: src/main.rs</span>
208
209 ```rust
210 {{#rustdoc_include ../listings/ch13-functional-features/listing-13-05/src/main.rs}}
211 ```
212
213 <span class="caption">Listing 13-5: Defining and calling a closure that
214 captures a mutable reference</span>
215
216 This code compiles, runs, and prints:
217
218 ```console
219 {{#include ../listings/ch13-functional-features/listing-13-05/output.txt}}
220 ```
221
222 Note that there’s no longer a `println!` between the definition and the call of
223 the `borrows_mutably` closure: when `borrows_mutably` is defined, it captures a
224 mutable reference to `list`. We don’t use the closure again after the closure
225 is called, so the mutable borrow ends. Between the closure definition and the
226 closure call, an immutable borrow to print isn’t allowed because no other
227 borrows are allowed when there’s a mutable borrow. Try adding a `println!`
228 there to see what error message you get!
229
230 If you want to force the closure to take ownership of the values it uses in the
231 environment even though the body of the closure doesn’t strictly need
232 ownership, you can use the `move` keyword before the parameter list. This
233 technique is mostly useful when passing a closure to a new thread to move the
234 data so that it’s owned by the new thread. We’ll have more examples of `move`
235 closures in Chapter 16 when we talk about concurrency.
236
237 <!-- Old headings. Do not remove or links may break. -->
238 <a id="storing-closures-using-generic-parameters-and-the-fn-traits"></a>
239 <a id="limitations-of-the-cacher-implementation"></a>
240 <a id="moving-captured-values-out-of-the-closure-and-the-fn-traits"></a>
241
242 ### Moving Captured Values Out of Closures and the `Fn` Traits
243
244 Once a closure has captured a reference or captured ownership of a value where
245 the closure is defined (thus affecting what, if anything, is moved *into* the
246 closure), the code in the body of the closure defines what happens to the
247 references or values when the closure is evaluated later (thus affecting what,
248 if anything, is moved *out of* the closure). A closure body can do any of the
249 following: move a captured value out of the closure, mutate the captured value,
250 neither move nor mutate the value, or capture nothing from the environment to
251 begin with.
252
253 The way a closure captures and handles values from the environment affects
254 which traits the closure implements, and traits are how functions and structs
255 can specify what kinds of closures they can use. Closures will automatically
256 implement one, two, or all three of these `Fn` traits, in an additive fashion:
257
258 1. `FnOnce` applies to closures that can be called at least once. All closures
259 implement at least this trait, because all closures can be called. A closure
260 that moves captured values out of its body will only implement `FnOnce`
261 and none of the other `Fn` traits, because it can only be called once.
262 2. `FnMut` applies to closures that don’t move captured values out of their
263 body, but that might mutate the captured values. These closures can be
264 called more than once.
265 3. `Fn` applies to closures that don’t move captured values out of their body
266 and that don’t mutate captured values, as well as closures that capture
267 nothing from their environment. These closures can be called more than once
268 without mutating their environment, which is important in cases such as
269 calling a closure multiple times concurrently.
270
271 Let’s look at the definition of the `unwrap_or_else` method on `Option<T>` that
272 we used in Listing 13-6:
273
274 ```rust,ignore
275 impl<T> Option<T> {
276 pub fn unwrap_or_else<F>(self, f: F) -> T
277 where
278 F: FnOnce() -> T
279 {
280 match self {
281 Some(x) => x,
282 None => f(),
283 }
284 }
285 }
286 ```
287
288 Recall that `T` is the generic type representing the type of the value in the
289 `Some` variant of an `Option`. That type `T` is also the return type of the
290 `unwrap_or_else` function: code that calls `unwrap_or_else` on an
291 `Option<String>`, for example, will get a `String`.
292
293 Next, notice that the `unwrap_or_else` function has the additional generic type
294 parameter `F`. The `F` type is the type of the parameter named `f`, which is
295 the closure we provide when calling `unwrap_or_else`.
296
297 The trait bound specified on the generic type `F` is `FnOnce() -> T`, which
298 means `F` must be able to be called at least once, take no arguments, and
299 return a `T`. Using `FnOnce` in the trait bound expresses the constraint that
300 `unwrap_or_else` is only going to call `f` at most one time. In the body of
301 `unwrap_or_else`, we can see that if the `Option` is `Some`, `f` won’t be
302 called. If the `Option` is `None`, `f` will be called once. Because all
303 closures implement `FnOnce`, `unwrap_or_else` accepts the most different kinds
304 of closures and is as flexible as it can be.
305
306 > Note: Functions can implement all three of the `Fn` traits too. If what we
307 > want to do doesn’t require capturing a value from the environment, we can use
308 > the name of a function rather than a closure where we need something that
309 > implements one of the `Fn` traits. For example, on an `Option<Vec<T>>` value,
310 > we could call `unwrap_or_else(Vec::new)` to get a new, empty vector if the
311 > value is `None`.
312
313 Now let’s look at the standard library method `sort_by_key` defined on slices,
314 to see how that differs from `unwrap_or_else` and why `sort_by_key` uses
315 `FnMut` instead of `FnOnce` for the trait bound.
316
317 The closure gets one argument, a reference to the current item in the slice
318 being considered, and returns a value of type `K` that can be ordered. This
319 function is useful when you want to sort a slice by a particular attribute of
320 each item. In Listing 13-x, we have a list of `Rectangle` instances and we use
321 `sort_by_key` to order them by their `width` attribute from low to high:
322
323 <span class="filename">Filename: src/main.rs</span>
324
325 ```rust
326 {{#rustdoc_include ../listings/ch13-functional-features/listing-13-07/src/main.rs}}
327 ```
328
329 <span class="caption">Listing 13-7: Using `sort_by_key` to order rectangles by
330 width</span>
331
332 This code prints:
333
334 ```console
335 {{#include ../listings/ch13-functional-features/listing-13-07/output.txt}}
336 ```
337
338 The reason `sort_by_key` is defined to take an `FnMut` closure is that it calls
339 the closure multiple times: once for each item in the slice. The closure `|r|
340 r.width` doesn’t capture, mutate, or move out anything from its environment, so
341 it meets the trait bound requirements.
342
343 In contrast, Listing 13-8 shows an example of a closure that implements just
344 the `FnOnce` trait, because it moves a value out of the environment. The
345 compiler won’t let us use this closure with `sort_by_key`:
346
347 <span class="filename">Filename: src/main.rs</span>
348
349 ```rust,ignore,does_not_compile
350 {{#rustdoc_include ../listings/ch13-functional-features/listing-13-08/src/main.rs}}
351 ```
352
353 <span class="caption">Listing 13-8: Attempting to use an `FnOnce` closure with
354 `sort_by_key`</span>
355
356 This is a contrived, convoluted way (that doesn’t work) to try and count the
357 number of times `sort_by_key` gets called when sorting `list`. This code
358 attempts to do this counting by pushing `value`—a `String` from the closure’s
359 environment—into the `sort_operations` vector. The closure captures `value`
360 then moves `value` out of the closure by transferring ownership of `value` to
361 the `sort_operations` vector. This closure can be called once; trying to call
362 it a second time wouldn’t work because `value` would no longer be in the
363 environment to be pushed into `sort_operations` again! Therefore, this closure
364 only implements `FnOnce`. When we try to compile this code, we get this error
365 that `value` can’t be moved out of the closure because the closure must
366 implement `FnMut`:
367
368 ```console
369 {{#include ../listings/ch13-functional-features/listing-13-08/output.txt}}
370 ```
371
372 The error points to the line in the closure body that moves `value` out of the
373 environment. To fix this, we need to change the closure body so that it doesn’t
374 move values out of the environment. To count the number of times `sort_by_key`
375 is called, keeping a counter in the environment and incrementing its value in
376 the closure body is a more straightforward way to calculate that. The closure
377 in Listing 13-x works with `sort_by_key` because it is only capturing a mutable
378 reference to the `num_sort_operations` counter and can therefore be called more
379 than once:
380
381 <span class="filename">Filename: src/main.rs</span>
382
383 ```rust
384 {{#rustdoc_include ../listings/ch13-functional-features/listing-13-09/src/main.rs}}
385 ```
386
387 <span class="caption">Listing 13-9: Using an `FnMut` closure with `sort_by_key`
388 is allowed</span>
389
390 The `Fn` traits are important when defining or using functions or types that
391 make use of closures. In the next section, we’ll discuss iterators. Many
392 iterator methods take closure arguments, so keep these closure details in mind
393 as we continue!
394
395 [unwrap-or-else]: ../std/option/enum.Option.html#method.unwrap_or_else