]> git.proxmox.com Git - rustc.git/blob - src/doc/book/second-edition/src/ch13-01-closures.md
New upstream version 1.25.0+dfsg1
[rustc.git] / src / doc / book / second-edition / src / ch13-01-closures.md
1 ## Closures: Anonymous Functions that Can Capture Their Environment
2
3 Rust’s *closures* are anonymous functions you can save in a variable or pass as
4 arguments to other functions. You can create the closure in one place, and then
5 call the closure to evaluate it in a different context. Unlike functions,
6 closures can capture values from the scope in which they’re called. We’ll
7 demonstrate how these closure features allow for code reuse and behavior
8 customization.
9
10 ### Creating an Abstraction of Behavior with Closures
11
12 Let’s work on an example of a situation in which it’s useful to store a closure
13 to be executed at a later time. Along the way, we’ll talk about the syntax of
14 closures, type inference, and traits.
15
16 Consider this hypothetical situation: we work at a startup that’s making an app
17 to generate custom exercise workout plans. The backend is written in Rust, and
18 the algorithm that generates the workout plan takes into account many different
19 factors, such as the app user’s age, body mass index, preferences, recent
20 workouts, and an intensity number they specify. The actual algorithm used isn’t
21 important in this example; what’s important is that this calculation takes a
22 few seconds. We want to call this algorithm only when we need to and only call
23 it once, so we don’t make the user wait more than necessary.
24
25 We’ll simulate calling this hypothetical algorithm with the
26 `simulated_expensive_calculation` function shown in Listing 13-1, which will
27 print `calculating slowly...`, wait for two seconds, and then return whatever
28 number we passed in:
29
30 <span class="filename">Filename: src/main.rs</span>
31
32 ```rust
33 use std::thread;
34 use std::time::Duration;
35
36 fn simulated_expensive_calculation(intensity: u32) -> u32 {
37 println!("calculating slowly...");
38 thread::sleep(Duration::from_secs(2));
39 intensity
40 }
41 ```
42
43 <span class="caption">Listing 13-1: A function to stand in for a hypothetical
44 calculation that takes about two seconds to run</span>
45
46 Next is the `main` function that contains the parts of the workout app
47 important for this example. This function represents the code that the app will
48 call when a user asks for a workout plan. Because the interaction with the
49 app’s frontend isn’t relevant to the use of closures, we’ll hardcode values
50 representing inputs to our program and print the outputs.
51
52 The required inputs are:
53
54 * *An intensity number from the user*, which is specified when they request
55 a workout to indicate whether they want a low-intensity workout or a
56 high-intensity workout.
57 * *A random number* that will generate some variety in the workout plans.
58
59 The output will be the recommended workout plan. Listing 13-2 shows the `main`
60 function we’ll use:
61
62 <span class="filename">Filename: src/main.rs</span>
63
64 ```rust
65 fn main() {
66 let simulated_user_specified_value = 10;
67 let simulated_random_number = 7;
68
69 generate_workout(
70 simulated_user_specified_value,
71 simulated_random_number
72 );
73 }
74 # fn generate_workout(intensity: u32, random_number: u32) {}
75 ```
76
77 <span class="caption">Listing 13-2: A `main` function with hardcoded values to
78 simulate user input and random number generation</span>
79
80 We’ve hardcoded the variable `simulated_user_specified_value` to 10 and the
81 variable `simulated_random_number` to 7 for simplicity’s sake; in an actual
82 program, we’d get the intensity number from the app frontend and we’d use the
83 `rand` crate to generate a random number, as we did in the Guessing Game
84 example in Chapter 2. The `main` function calls a `generate_workout` function
85 with the simulated input values.
86
87 Now that we have the context, let’s get to the algorithm. The
88 `generate_workout` function in Listing 13-3 contains the business logic of the
89 app that we’re most concerned with in this example. The rest of the code
90 changes in this example will be made to this function:
91
92 <span class="filename">Filename: src/main.rs</span>
93
94 ```rust
95 # use std::thread;
96 # use std::time::Duration;
97 #
98 # fn simulated_expensive_calculation(num: u32) -> u32 {
99 # println!("calculating slowly...");
100 # thread::sleep(Duration::from_secs(2));
101 # num
102 # }
103 #
104 fn generate_workout(intensity: u32, random_number: u32) {
105 if intensity < 25 {
106 println!(
107 "Today, do {} pushups!",
108 simulated_expensive_calculation(intensity)
109 );
110 println!(
111 "Next, do {} situps!",
112 simulated_expensive_calculation(intensity)
113 );
114 } else {
115 if random_number == 3 {
116 println!("Take a break today! Remember to stay hydrated!");
117 } else {
118 println!(
119 "Today, run for {} minutes!",
120 simulated_expensive_calculation(intensity)
121 );
122 }
123 }
124 }
125 ```
126
127 <span class="caption">Listing 13-3: The business logic that prints the workout
128 plans based on the inputs and calls to the `simulated_expensive_calculation`
129 function</span>
130
131 The code in Listing 13-3 has multiple calls to the slow calculation function.
132 The first `if` block calls `simulated_expensive_calculation` twice, the `if`
133 inside the outer `else` doesn’t call it at all, and the code inside the
134 second `else` case calls it once.
135
136 <!-- NEXT PARAGRAPH WRAPPED WEIRD INTENTIONALLY SEE #199 -->
137
138 The desired behavior of the `generate_workout` function is to first check
139 whether the user wants a low-intensity workout (indicated by a number less
140 than 25) or a high-intensity workout (a number of 25 or greater).
141
142 Low-intensity workout plans will recommend a number of push-ups and sit-ups
143 based on the complex algorithm we’re simulating.
144
145 If the user wants a high-intensity workout, there’s some additional logic: if
146 the value of the random number generated by the app happens to be 3, the app
147 will recommend a break and hydration. If not, the user will get a number of
148 minutes of running based on the complex algorithm.
149
150 The data science team has let us know that we’ll have to make some changes to
151 the way we call the algorithm in the future. To simplify the update when those
152 changes happen, we want to refactor this code so it calls the
153 `simulated_expensive_calculation` function only once. We also want to cut the
154 place where we’re currently unnecessarily calling the function twice without
155 adding any other calls to that function in the process. That is, we don’t want
156 to call it if the result isn’t needed, and we still want to call it only once.
157
158 #### Refactoring Using Functions
159
160 We could restructure the workout program in many ways. First, we’ll try
161 extracting the duplicated call to the `expensive_calculation` function into
162 a variable, as shown in Listing 13-4:
163
164 <span class="filename">Filename: src/main.rs</span>
165
166 ```rust
167 # use std::thread;
168 # use std::time::Duration;
169 #
170 # fn simulated_expensive_calculation(num: u32) -> u32 {
171 # println!("calculating slowly...");
172 # thread::sleep(Duration::from_secs(2));
173 # num
174 # }
175 #
176 fn generate_workout(intensity: u32, random_number: u32) {
177 let expensive_result =
178 simulated_expensive_calculation(intensity);
179
180 if intensity < 25 {
181 println!(
182 "Today, do {} pushups!",
183 expensive_result
184 );
185 println!(
186 "Next, do {} situps!",
187 expensive_result
188 );
189 } else {
190 if random_number == 3 {
191 println!("Take a break today! Remember to stay hydrated!");
192 } else {
193 println!(
194 "Today, run for {} minutes!",
195 expensive_result
196 );
197 }
198 }
199 }
200 ```
201
202 <span class="caption">Listing 13-4: Extracting the calls to
203 `simulated_expensive_calculation` to one place and storing the result in the
204 `expensive_result` variable</span>
205
206 This change unifies all the calls to `simulated_expensive_calculation` and
207 solves the problem of the first `if` block unnecessarily calling the function
208 twice. Unfortunately, we’re now calling this function and waiting for the
209 result in all cases, which includes the inner `if` block that doesn’t use the
210 result value at all.
211
212 We want to define code in one place in our program, but only *execute* that
213 code where we actually need the result. This is a use case for closures!
214
215 #### Refactoring with Closures to Store Code
216
217 Instead of always calling the `simulated_expensive_calculation` function before
218 the `if` blocks, we can define a closure and store the *closure* in a variable
219 rather than storing the result, as shown in Listing 13-5. We can actually move
220 the whole body of `simulated_expensive_calculation` within the closure we’re
221 introducing here:
222
223 <span class="filename">Filename: src/main.rs</span>
224
225 ```rust
226 # use std::thread;
227 # use std::time::Duration;
228 #
229 let expensive_closure = |num| {
230 println!("calculating slowly...");
231 thread::sleep(Duration::from_secs(2));
232 num
233 };
234 # expensive_closure(5);
235 ```
236
237 <span class="caption">Listing 13-5: Defining a closure and storing it in the
238 `expensive_closure` variable</span>
239
240 The closure definition comes after the `=` to assign it to the variable
241 `expensive_closure`. To define a closure, we start with a pair of vertical
242 pipes (`|`), inside which we specify the parameters to the closure; this syntax
243 was chosen because of its similarity to closure definitions in Smalltalk and
244 Ruby. This closure has one parameter named `num`: if we had more than one
245 parameter, we would separate them with commas, like `|param1, param2|`.
246
247 After the parameters, we place curly brackets that hold the body of the
248 closure—these are optional if the closure body is a single expression. The end
249 of the closure, after the curly brackets, needs a semicolon to complete the
250 `let` statement. The value returned from the last line in the closure body
251 (`num`) will be the value returned from the closure when it’s called, because
252 that line doesn’t end in a semicolon; just like in function bodies.
253
254 Note that this `let` statement means `expensive_closure` contains the
255 *definition* of an anonymous function, not the *resulting value* of calling the
256 anonymous function. Recall that we’re using a closure because we want to define
257 the code to call at one point, store that code, and call it at a later point;
258 the code we want to call is now stored in `expensive_closure`.
259
260 With the closure defined, we can change the code in the `if` blocks to call the
261 closure to execute the code and get the resulting value. We call a closure like
262 we do a function: we specify the variable name that holds the closure
263 definition and follow it with parentheses containing the argument values we
264 want to use, as shown in Listing 13-6:
265
266 <span class="filename">Filename: src/main.rs</span>
267
268 ```rust
269 # use std::thread;
270 # use std::time::Duration;
271 #
272 fn generate_workout(intensity: u32, random_number: u32) {
273 let expensive_closure = |num| {
274 println!("calculating slowly...");
275 thread::sleep(Duration::from_secs(2));
276 num
277 };
278
279 if intensity < 25 {
280 println!(
281 "Today, do {} pushups!",
282 expensive_closure(intensity)
283 );
284 println!(
285 "Next, do {} situps!",
286 expensive_closure(intensity)
287 );
288 } else {
289 if random_number == 3 {
290 println!("Take a break today! Remember to stay hydrated!");
291 } else {
292 println!(
293 "Today, run for {} minutes!",
294 expensive_closure(intensity)
295 );
296 }
297 }
298 }
299 ```
300
301 <span class="caption">Listing 13-6: Calling the `expensive_closure` we’ve
302 defined</span>
303
304 Now the expensive calculation is called in only one place, and we’re only
305 executing that code where we need the results.
306
307 However, we’ve reintroduced one of the problems from Listing 13-3: we’re still
308 calling the closure twice in the first `if` block, which will call the
309 expensive code twice and make the user wait twice as long as they need to. We
310 could fix this problem by creating a variable local to that `if` block to hold
311 the result of calling the closure, but closures provide us with another
312 solution. We’ll talk about that solution in a bit. But first let’s talk about
313 why there aren’t type annotations in the closure definition and the traits
314 involved with closures.
315
316 ### Closure Type Inference and Annotation
317
318 Closures don’t require you to annotate the types of the parameters or the
319 return value like `fn` functions do. Type annotations are required on functions
320 because they’re part of an explicit interface exposed to your users. Defining
321 this interface rigidly is important for ensuring that everyone agrees on what
322 types of values a function uses and returns. But closures aren’t used in an
323 exposed interface like this: they’re stored in variables and used without
324 naming them and exposing them to users of our library.
325
326 Additionally, closures are usually short and only relevant within a narrow
327 context rather than in any arbitrary scenario. Within these limited contexts,
328 the compiler is reliably able to infer the types of the parameters and return
329 type, similar to how it’s able to infer the types of most variables.
330
331 Making programmers annotate the types in these small, anonymous functions would
332 be annoying and largely redundant with the information the compiler already has
333 available.
334
335 Like variables, we can add type annotations if we want to increase explicitness
336 and clarity at the cost of being more verbose than is strictly necessary;
337 annotating the types for the closure we defined in Listing 13-4 would look like
338 the definition shown in Listing 13-7:
339
340 <span class="filename">Filename: src/main.rs</span>
341
342 ```rust
343 # use std::thread;
344 # use std::time::Duration;
345 #
346 let expensive_closure = |num: u32| -> u32 {
347 println!("calculating slowly...");
348 thread::sleep(Duration::from_secs(2));
349 num
350 };
351 ```
352
353 <span class="caption">Listing 13-7: Adding optional type annotations of the
354 parameter and return value types in the closure</span>
355
356 The syntax of closures and functions looks more similar with type annotations.
357 The following is a vertical comparison of the syntax for the definition of a
358 function that adds one to its parameter, and a closure that has the same
359 behavior. We’ve added some spaces to line up the relevant parts. This
360 illustrates how closure syntax is similar to function syntax except for the use
361 of pipes and the amount of syntax that is optional:
362
363 ```rust,ignore
364 fn add_one_v1 (x: u32) -> u32 { x + 1 }
365 let add_one_v2 = |x: u32| -> u32 { x + 1 };
366 let add_one_v3 = |x| { x + 1 };
367 let add_one_v4 = |x| x + 1 ;
368 ```
369
370 The first line shows a function definition, and the second line shows a fully
371 annotated closure definition. The third line removes the type annotations from
372 the closure definition, and the fourth line removes the brackets that are
373 optional, because the closure body has only one expression. These are all valid
374 definitions that will produce the same behavior when they’re called.
375
376 Closure definitions will have one concrete type inferred for each of their
377 parameters and for their return value. For instance, Listing 13-8 shows the
378 definition of a short closure that just returns the value it receives as a
379 parameter. This closure isn’t very useful except for the purposes of this
380 example. Note that we haven’t added any type annotations to the definition: if
381 we then try to call the closure twice, using a `String` as an argument the
382 first time and a `u32` the second time, we’ll get an error:
383
384 <span class="filename">Filename: src/main.rs</span>
385
386 ```rust,ignore
387 let example_closure = |x| x;
388
389 let s = example_closure(String::from("hello"));
390 let n = example_closure(5);
391 ```
392
393 <span class="caption">Listing 13-8: Attempting to call a closure whose types
394 are inferred with two different types</span>
395
396 The compiler gives us this error:
397
398 ```text
399 error[E0308]: mismatched types
400 --> src/main.rs
401 |
402 | let n = example_closure(5);
403 | ^ expected struct `std::string::String`, found
404 integral variable
405 |
406 = note: expected type `std::string::String`
407 found type `{integer}`
408 ```
409
410 The first time we call `example_closure` with the `String` value, the compiler
411 infers the type of `x` and the return type of the closure to be `String`. Those
412 types are then locked in to the closure in `example_closure`, and we get a type
413 error if we try to use a different type with the same closure.
414
415 ### Storing Closures Using Generic Parameters and the `Fn` Traits
416
417 Let’s return to our workout generation app. In Listing 13-6, our code was still
418 calling the expensive calculation closure more times than it needed to. One
419 option to solve this issue is to save the result of the expensive closure in a
420 variable for reuse and use the variable instead in each place we need the
421 result instead of calling the closure again. However, this method could result
422 in a lot of repeated code.
423
424 Fortunately, another solution is available to us. We can create a struct that
425 will hold the closure and the resulting value of calling the closure. The
426 struct will only execute the closure if we need the resulting value, and it
427 will cache the resulting value so the rest of our code doesn’t have to be
428 responsible for saving and reusing the result. You may know this pattern as
429 *memoization* or *lazy evaluation*.
430
431 To make a struct that holds a closure, we need to specify the type of the
432 closure, because a struct definition needs to know the types of each of its
433 fields. Each closure instance has its own unique anonymous type: that is, even
434 if two closures have the same signature, their types are still considered
435 different. To define structs, enums, or function parameters that use closures,
436 we use generics and trait bounds, as we discussed in Chapter 10.
437
438 The `Fn` traits are provided by the standard library. All closures implement
439 one of the traits: `Fn`, `FnMut`, or `FnOnce`. We’ll discuss the difference
440 between these traits in the next section on capturing the environment; in this
441 example, we can use the `Fn` trait.
442
443 We add types to the `Fn` trait bound to represent the types of the parameters
444 and return values the closures must have to match this trait bound. In this
445 case, our closure has a parameter of type `u32` and returns a `u32`, so the
446 trait bound we specify is `Fn(u32) -> u32`.
447
448 Listing 13-9 shows the definition of the `Cacher` struct that holds a closure
449 and an optional result value:
450
451 <span class="filename">Filename: src/main.rs</span>
452
453 ```rust
454 struct Cacher<T>
455 where T: Fn(u32) -> u32
456 {
457 calculation: T,
458 value: Option<u32>,
459 }
460 ```
461
462 <span class="caption">Listing 13-9: Defining a `Cacher` struct that holds a
463 closure in `calculation` and an optional result in `value`</span>
464
465 The `Cacher` struct has a `calculation` field of the generic type `T`. The
466 trait bounds on `T` specify that it’s a closure by using the `Fn` trait. Any
467 closure we want to store in the `calculation` field must have one `u32`
468 parameter (specified within the parentheses after `Fn`) and must return a
469 `u32` (specified after the `->`).
470
471 > Note: Functions implement all three of the `Fn` traits too. If what we want
472 > to do doesn’t require capturing a value from the environment, we can use a
473 > function rather than a closure where we need something that implements an `Fn`
474 > trait.
475
476 The `value` field is of type `Option<u32>`. Before we execute the closure,
477 `value` will be `None`. When code using a `Cacher` asks for the *result* of the
478 closure, the `Cacher` will execute the closure at that time and store the
479 result within a `Some` variant in the `value` field. Then if the code asks for
480 the result of the closure again, instead of executing the closure again, the
481 `Cacher` will return the result held in the `Some` variant.
482
483 The logic around the `value` field we’ve just described is defined in Listing
484 13-10:
485
486 <span class="filename">Filename: src/main.rs</span>
487
488 ```rust
489 # struct Cacher<T>
490 # where T: Fn(u32) -> u32
491 # {
492 # calculation: T,
493 # value: Option<u32>,
494 # }
495 #
496 impl<T> Cacher<T>
497 where T: Fn(u32) -> u32
498 {
499 fn new(calculation: T) -> Cacher<T> {
500 Cacher {
501 calculation,
502 value: None,
503 }
504 }
505
506 fn value(&mut self, arg: u32) -> u32 {
507 match self.value {
508 Some(v) => v,
509 None => {
510 let v = (self.calculation)(arg);
511 self.value = Some(v);
512 v
513 },
514 }
515 }
516 }
517 ```
518
519 <span class="caption">Listing 13-10: The caching logic of `Cacher`</span>
520
521 We want `Cacher` to manage the struct fields’ values rather than letting the
522 calling code potentially change the values in these fields directly, so these
523 fields are private.
524
525 The `Cacher::new` function takes a generic parameter `T`, which we’ve defined
526 as having the same trait bound as the `Cacher` struct. Then `Cacher::new`
527 returns a `Cacher` instance that holds the closure specified in the
528 `calculation` field and a `None` value in the `value` field, because we haven’t
529 executed the closure yet.
530
531 When the calling code wants the result of evaluating the closure, instead of
532 calling the closure directly, it will call the `value` method. This method
533 checks whether we already have a resulting value in `self.value` in a `Some`;
534 if we do, it returns the value within the `Some` without executing the closure
535 again.
536
537 If `self.value` is `None`, we call the closure stored in `self.calculation`,
538 save the result in `self.value` for future use, and return the value as well.
539
540 Listing 13-11 shows how we can use this `Cacher` struct in the
541 `generate_workout` function from Listing 13-6:
542
543 <span class="filename">Filename: src/main.rs</span>
544
545 ```rust
546 # use std::thread;
547 # use std::time::Duration;
548 #
549 # struct Cacher<T>
550 # where T: Fn(u32) -> u32
551 # {
552 # calculation: T,
553 # value: Option<u32>,
554 # }
555 #
556 # impl<T> Cacher<T>
557 # where T: Fn(u32) -> u32
558 # {
559 # fn new(calculation: T) -> Cacher<T> {
560 # Cacher {
561 # calculation,
562 # value: None,
563 # }
564 # }
565 #
566 # fn value(&mut self, arg: u32) -> u32 {
567 # match self.value {
568 # Some(v) => v,
569 # None => {
570 # let v = (self.calculation)(arg);
571 # self.value = Some(v);
572 # v
573 # },
574 # }
575 # }
576 # }
577 #
578 fn generate_workout(intensity: u32, random_number: u32) {
579 let mut expensive_result = Cacher::new(|num| {
580 println!("calculating slowly...");
581 thread::sleep(Duration::from_secs(2));
582 num
583 });
584
585 if intensity < 25 {
586 println!(
587 "Today, do {} pushups!",
588 expensive_result.value(intensity)
589 );
590 println!(
591 "Next, do {} situps!",
592 expensive_result.value(intensity)
593 );
594 } else {
595 if random_number == 3 {
596 println!("Take a break today! Remember to stay hydrated!");
597 } else {
598 println!(
599 "Today, run for {} minutes!",
600 expensive_result.value(intensity)
601 );
602 }
603 }
604 }
605 ```
606
607 <span class="caption">Listing 13-11: Using `Cacher` in the `generate_workout`
608 function to abstract away the caching logic</span>
609
610 Instead of saving the closure in a variable directly, we save a new instance of
611 `Cacher` that holds the closure. Then, in each place we want the result, we
612 call the `value` method on the `Cacher` instance. We can call the `value`
613 method as many times as we want, or not call it at all, and the expensive
614 calculation will be run a maximum of once.
615
616 Try running this program with the `main` function from Listing 13-2. Change the
617 values in the `simulated_user_specified_value` and `simulated_random_number`
618 variables to verify that in all the cases in the various `if` and `else`
619 blocks, `calculating slowly...` only appears once and only when needed. The
620 `Cacher` takes care of the logic necessary to ensure we aren’t calling the
621 expensive calculation more than we need to, so `generate_workout` can focus on
622 the business logic.
623
624 ### Limitations of the `Cacher` Implementation
625
626 Caching values is a generally useful behavior that we might want to use in
627 other parts of our code with different closures. However, there are two
628 problems with the current implementation of `Cacher` that would make reusing it
629 in different contexts difficult.
630
631 The first problem is that a `Cacher` instance assumes it will always get the
632 same value for the parameter `arg` to the `value` method. That is, this test of
633 `Cacher` will fail:
634
635 ```rust,ignore
636 #[test]
637 fn call_with_different_values() {
638 let mut c = Cacher::new(|a| a);
639
640 let v1 = c.value(1);
641 let v2 = c.value(2);
642
643 assert_eq!(v2, 2);
644 }
645 ```
646
647 This test creates a new `Cacher` instance with a closure that returns the value
648 passed into it. We call the `value` method on this `Cacher` instance with an
649 `arg` value of 1 and then an `arg` value of 2, and we expect that the call to
650 `value` with the `arg` value of 2 should return 2.
651
652 Run this test with the `Cacher` implementation in Listing 13-9 and Listing
653 13-10, and the test will fail on the `assert_eq!` with this message:
654
655 ```text
656 thread 'call_with_different_values' panicked at 'assertion failed: `(left == right)`
657 left: `1`,
658 right: `2`', src/main.rs
659 ```
660
661 The problem is that the first time we called `c.value` with 1, the `Cacher`
662 instance saved `Some(1)` in `self.value`. Thereafter, no matter what we pass in
663 to the `value` method, it will always return 1.
664
665 Try modifying `Cacher` to hold a hash map rather than a single value. The keys
666 of the hash map will be the `arg` values that are passed in, and the values of
667 the hash map will be the result of calling the closure on that key. Instead of
668 looking at whether `self.value` directly has a `Some` or a `None` value, the
669 `value` function will look up the `arg` in the hash map and return the value if
670 it’s present. If it’s not present, the `Cacher` will call the closure and save
671 the resulting value in the hash map associated with its `arg` value.
672
673 The second problem with the current `Cacher` implementation is that it only
674 accepts closures that take one parameter of type `u32` and return a `u32`. We
675 might want to cache the results of closures that take a string slice and return
676 `usize` values, for example. To fix this issue, try introducing more generic
677 parameters to increase the flexibility of the `Cacher` functionality.
678
679 ### Capturing the Environment with Closures
680
681 In the workout generator example, we only used closures as inline anonymous
682 functions. However, closures have an additional capability that functions don’t
683 have: they can capture their environment and access variables from the scope in
684 which they’re defined.
685
686 Listing 13-12 has an example of a closure stored in the variable `equal_to_x`
687 that uses the variable `x` from the closure’s surrounding environment:
688
689 <span class="filename">Filename: src/main.rs</span>
690
691 ```rust
692 fn main() {
693 let x = 4;
694
695 let equal_to_x = |z| z == x;
696
697 let y = 4;
698
699 assert!(equal_to_x(y));
700 }
701 ```
702
703 <span class="caption">Listing 13-12: Example of a closure that refers to a
704 variable in its enclosing scope</span>
705
706 Here, even though `x` is not one of the parameters of `equal_to_x`, the
707 `equal_to_x` closure is allowed to use the `x` variable that’s defined in the
708 same scope that `equal_to_x` is defined in.
709
710 We can’t do the same with functions; if we try with the following example, our
711 code won’t compile:
712
713 <span class="filename">Filename: src/main.rs</span>
714
715 ```rust,ignore
716 fn main() {
717 let x = 4;
718
719 fn equal_to_x(z: i32) -> bool { z == x }
720
721 let y = 4;
722
723 assert!(equal_to_x(y));
724 }
725 ```
726
727 We get an error:
728
729 ```text
730 error[E0434]: can't capture dynamic environment in a fn item; use the || { ...
731 } closure form instead
732 --> src/main.rs
733 |
734 4 | fn equal_to_x(z: i32) -> bool { z == x }
735 | ^
736 ```
737
738 The compiler even reminds us that this only works with closures!
739
740 When a closure captures a value from its environment, it uses memory to store
741 the values for use in the closure body. This use of memory is overhead that we
742 don’t want to pay in more common cases where we want to execute code that
743 doesn’t capture its environment. Because functions are never allowed to capture
744 their environment, defining and using functions will never incur this overhead.
745
746 Closures can capture values from their environment in three ways, which
747 directly map to the three ways a function can take a parameter: taking
748 ownership, borrowing immutably, and borrowing mutably. These are encoded in the
749 three `Fn` traits as follows:
750
751 * `FnOnce` consumes the variables it captures from its enclosing scope, known
752 as the closure’s *environment*. To consume the captured variables, the
753 closure must take ownership of these variables and move them into the closure
754 when it is defined. The `Once` part of the name represents the fact that the
755 closure can’t take ownership of the same variables more than once, so it can
756 be called only once.
757 * `Fn` borrows values from the environment immutably.
758 * `FnMut` can change the environment because it mutably borrows values.
759
760 When we create a closure, Rust infers which trait to use based on how the
761 closure uses the values from the environment. In Listing 13-12, the
762 `equal_to_x` closure borrows `x` immutably (so `equal_to_x` has the `Fn` trait)
763 because the body of the closure only needs to read the value in `x`.
764
765 If we want to force the closure to take ownership of the values it uses in the
766 environment, we can use the `move` keyword before the parameter list. This
767 technique is mostly useful when passing a closure to a new thread to move the
768 data so it’s owned by the new thread.
769
770 We’ll have more examples of `move` closures in Chapter 16 when we talk about
771 concurrency. For now, here’s the code from Listing 13-12 with the `move`
772 keyword added to the closure definition and using vectors instead of integers,
773 because integers can be copied rather than moved; note that this code will not
774 yet compile:
775
776 <span class="filename">Filename: src/main.rs</span>
777
778 ```rust,ignore
779 fn main() {
780 let x = vec![1, 2, 3];
781
782 let equal_to_x = move |z| z == x;
783
784 println!("can't use x here: {:?}", x);
785
786 let y = vec![1, 2, 3];
787
788 assert!(equal_to_x(y));
789 }
790 ```
791
792 We receive the following error:
793
794 ```text
795 error[E0382]: use of moved value: `x`
796 --> src/main.rs:6:40
797 |
798 4 | let equal_to_x = move |z| z == x;
799 | -------- value moved (into closure) here
800 5 |
801 6 | println!("can't use x here: {:?}", x);
802 | ^ value used here after move
803 |
804 = note: move occurs because `x` has type `std::vec::Vec<i32>`, which does not
805 implement the `Copy` trait
806 ```
807
808 The `x` value is moved into the closure when the closure is defined, because we
809 added the `move` keyword. The closure then has ownership of `x`, and `main`
810 isn’t allowed to use `x` anymore in the `println!` statement. Removing
811 `println!` will fix this example.
812
813 Most of the time when specifying one of the `Fn` trait bounds, you can start
814 with `Fn` and the compiler will tell you if you need `FnMut` or `FnOnce` based
815 on what happens in the closure body.
816
817 To illustrate situations where closures that can capture their environment are
818 useful as function parameters, let’s move on to our next topic: iterators.