]> git.proxmox.com Git - rustc.git/blob - src/doc/book/src/ch13-01-closures.md
New upstream version 1.64.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 `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. The
136 `add_one_v3` and `add_one_v4` lines require the closures to be evaluated 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.
233
234 This technique is mostly useful when passing a closure to a new thread to move
235 the data so that it’s owned by the new thread. We’ll discuss threads and why
236 you would want to use them in detail in Chapter 16 when we talk about
237 concurrency, but for now, let’s briefly explore spawning a new thread using a
238 closure that needs the `move` keyword. Listing 13-6 shows Listing 13-4 modified
239 to print the vector in a new thread rather than in the main thread:
240
241 <span class="filename">Filename: src/main.rs</span>
242
243 ```rust
244 {{#rustdoc_include ../listings/ch13-functional-features/listing-13-06/src/main.rs}}
245 ```
246
247 <span class="caption">Listing 13-6: Using `move` to force the closure for the
248 thread to take ownership of `list`</span>
249
250 We spawn a new thread, giving the thread a closure to run as an argument. The
251 closure body prints out the list. In Listing 13-4, the closure only captured
252 `list` using an immutable reference because that's the least amount of access
253 to `list` needed to print it. In this example, even though the closure body
254 still only needs an immutable reference, we need to specify that `list` should
255 be moved into the closure by putting the `move` keyword at the beginning of the
256 closure definition. The new thread might finish before the rest of the main
257 thread finishes, or the main thread might finish first. If the main thread
258 maintained ownership of `list` but ended before the new thread did and dropped
259 `list`, the immutable reference in the thread would be invalid. Therefore, the
260 compiler requires that `list` be moved into the closure given to the new thread
261 so the reference will be valid. Try removing the `move` keyword or using `list`
262 in the main thread after the closure is defined to see what compiler errors you
263 get!
264
265 <!-- Old headings. Do not remove or links may break. -->
266 <a id="storing-closures-using-generic-parameters-and-the-fn-traits"></a>
267 <a id="limitations-of-the-cacher-implementation"></a>
268 <a id="moving-captured-values-out-of-the-closure-and-the-fn-traits"></a>
269
270 ### Moving Captured Values Out of Closures and the `Fn` Traits
271
272 Once a closure has captured a reference or captured ownership of a value from
273 the environment where the closure is defined (thus affecting what, if anything,
274 is moved *into* the closure), the code in the body of the closure defines what
275 happens to the references or values when the closure is evaluated later (thus
276 affecting what, if anything, is moved *out of* the closure). A closure body can
277 do any of the following: move a captured value out of the closure, mutate the
278 captured value, neither move nor mutate the value, or capture nothing from the
279 environment to begin with.
280
281 The way a closure captures and handles values from the environment affects
282 which traits the closure implements, and traits are how functions and structs
283 can specify what kinds of closures they can use. Closures will automatically
284 implement one, two, or all three of these `Fn` traits, in an additive fashion,
285 depending on how the closure’s body handles the values:
286
287 1. `FnOnce` applies to closures that can be called once. All closures implement
288 at least this trait, because all closures can be called. A closure that
289 moves captured values out of its body will only implement `FnOnce` and none
290 of the other `Fn` traits, because it can only be called once.
291 2. `FnMut` applies to closures that don’t move captured values out of their
292 body, but that might mutate the captured values. These closures can be
293 called more than once.
294 3. `Fn` applies to closures that don’t move captured values out of their body
295 and that don’t mutate captured values, as well as closures that capture
296 nothing from their environment. These closures can be called more than once
297 without mutating their environment, which is important in cases such as
298 calling a closure multiple times concurrently.
299
300 Let’s look at the definition of the `unwrap_or_else` method on `Option<T>` that
301 we used in Listing 13-1:
302
303 ```rust,ignore
304 impl<T> Option<T> {
305 pub fn unwrap_or_else<F>(self, f: F) -> T
306 where
307 F: FnOnce() -> T
308 {
309 match self {
310 Some(x) => x,
311 None => f(),
312 }
313 }
314 }
315 ```
316
317 Recall that `T` is the generic type representing the type of the value in the
318 `Some` variant of an `Option`. That type `T` is also the return type of the
319 `unwrap_or_else` function: code that calls `unwrap_or_else` on an
320 `Option<String>`, for example, will get a `String`.
321
322 Next, notice that the `unwrap_or_else` function has the additional generic type
323 parameter `F`. The `F` type is the type of the parameter named `f`, which is
324 the closure we provide when calling `unwrap_or_else`.
325
326 The trait bound specified on the generic type `F` is `FnOnce() -> T`, which
327 means `F` must be able to be called once, take no arguments, and return a `T`.
328 Using `FnOnce` in the trait bound expresses the constraint that
329 `unwrap_or_else` is only going to call `f` at most one time. In the body of
330 `unwrap_or_else`, we can see that if the `Option` is `Some`, `f` won’t be
331 called. If the `Option` is `None`, `f` will be called once. Because all
332 closures implement `FnOnce`, `unwrap_or_else` accepts the most different kinds
333 of closures and is as flexible as it can be.
334
335 > Note: Functions can implement all three of the `Fn` traits too. If what we
336 > want to do doesn’t require capturing a value from the environment, we can use
337 > the name of a function rather than a closure where we need something that
338 > implements one of the `Fn` traits. For example, on an `Option<Vec<T>>` value,
339 > we could call `unwrap_or_else(Vec::new)` to get a new, empty vector if the
340 > value is `None`.
341
342 Now let’s look at the standard library method `sort_by_key` defined on slices,
343 to see how that differs from `unwrap_or_else` and why `sort_by_key` uses
344 `FnMut` instead of `FnOnce` for the trait bound. The closure gets one argument
345 in the form of a reference to the current item in the slice being considered,
346 and returns a value of type `K` that can be ordered. This function is useful
347 when you want to sort a slice by a particular attribute of each item. In
348 Listing 13-7, we have a list of `Rectangle` instances and we use `sort_by_key`
349 to order them by their `width` attribute from low to high:
350
351 <span class="filename">Filename: src/main.rs</span>
352
353 ```rust
354 {{#rustdoc_include ../listings/ch13-functional-features/listing-13-07/src/main.rs}}
355 ```
356
357 <span class="caption">Listing 13-7: Using `sort_by_key` to order rectangles by
358 width</span>
359
360 This code prints:
361
362 ```console
363 {{#include ../listings/ch13-functional-features/listing-13-07/output.txt}}
364 ```
365
366 The reason `sort_by_key` is defined to take an `FnMut` closure is that it calls
367 the closure multiple times: once for each item in the slice. The closure `|r|
368 r.width` doesn’t capture, mutate, or move out anything from its environment, so
369 it meets the trait bound requirements.
370
371 In contrast, Listing 13-8 shows an example of a closure that implements just
372 the `FnOnce` trait, because it moves a value out of the environment. The
373 compiler won’t let us use this closure with `sort_by_key`:
374
375 <span class="filename">Filename: src/main.rs</span>
376
377 ```rust,ignore,does_not_compile
378 {{#rustdoc_include ../listings/ch13-functional-features/listing-13-08/src/main.rs}}
379 ```
380
381 <span class="caption">Listing 13-8: Attempting to use an `FnOnce` closure with
382 `sort_by_key`</span>
383
384 This is a contrived, convoluted way (that doesn’t work) to try and count the
385 number of times `sort_by_key` gets called when sorting `list`. This code
386 attempts to do this counting by pushing `value`—a `String` from the closure’s
387 environment—into the `sort_operations` vector. The closure captures `value`
388 then moves `value` out of the closure by transferring ownership of `value` to
389 the `sort_operations` vector. This closure can be called once; trying to call
390 it a second time wouldn’t work because `value` would no longer be in the
391 environment to be pushed into `sort_operations` again! Therefore, this closure
392 only implements `FnOnce`. When we try to compile this code, we get this error
393 that `value` can’t be moved out of the closure because the closure must
394 implement `FnMut`:
395
396 ```console
397 {{#include ../listings/ch13-functional-features/listing-13-08/output.txt}}
398 ```
399
400 The error points to the line in the closure body that moves `value` out of the
401 environment. To fix this, we need to change the closure body so that it doesn’t
402 move values out of the environment. To count the number of times `sort_by_key`
403 is called, keeping a counter in the environment and incrementing its value in
404 the closure body is a more straightforward way to calculate that. The closure
405 in Listing 13-9 works with `sort_by_key` because it is only capturing a mutable
406 reference to the `num_sort_operations` counter and can therefore be called more
407 than once:
408
409 <span class="filename">Filename: src/main.rs</span>
410
411 ```rust
412 {{#rustdoc_include ../listings/ch13-functional-features/listing-13-09/src/main.rs}}
413 ```
414
415 <span class="caption">Listing 13-9: Using an `FnMut` closure with `sort_by_key`
416 is allowed</span>
417
418 The `Fn` traits are important when defining or using functions or types that
419 make use of closures. In the next section, we’ll discuss iterators. Many
420 iterator methods take closure arguments, so keep these closure details in mind
421 as we continue!
422
423 [unwrap-or-else]: ../std/option/enum.Option.html#method.unwrap_or_else