]> git.proxmox.com Git - rustc.git/blame - src/doc/book/src/ch13-01-closures.md
Merge tag 'debian/1.52.1+dfsg1-1_exp2' into proxmox/buster
[rustc.git] / src / doc / book / src / ch13-01-closures.md
CommitLineData
13cf67c4
XL
1## Closures: Anonymous Functions that Can Capture Their Environment
2
3Rust’s closures are anonymous functions you can save in a variable or pass as
4arguments to other functions. You can create the closure in one place and then
5call the closure to evaluate it in a different context. Unlike functions,
6closures can capture values from the scope in which they’re defined. We’ll
7demonstrate how these closure features allow for code reuse and behavior
8customization.
9
10### Creating an Abstraction of Behavior with Closures
11
12Let’s work on an example of a situation in which it’s useful to store a closure
13to be executed later. Along the way, we’ll talk about the syntax of closures,
14type inference, and traits.
15
16Consider this hypothetical situation: we work at a startup that’s making an app
17to generate custom exercise workout plans. The backend is written in Rust, and
18the algorithm that generates the workout plan takes into account many factors,
19such as the app user’s age, body mass index, exercise preferences, recent
20workouts, and an intensity number they specify. The actual algorithm used isn’t
21important in this example; what’s important is that this calculation takes a
22few seconds. We want to call this algorithm only when we need to and only call
23it once so we don’t make the user wait more than necessary.
24
25We’ll simulate calling this hypothetical algorithm with the function
26`simulated_expensive_calculation` shown in Listing 13-1, which will print
27`calculating slowly...`, wait for two seconds, and then return whatever number
9fa01778 28we passed in.
13cf67c4
XL
29
30<span class="filename">Filename: src/main.rs</span>
31
32```rust
74b04a01 33{{#rustdoc_include ../listings/ch13-functional-features/listing-13-01/src/main.rs:here}}
13cf67c4
XL
34```
35
36<span class="caption">Listing 13-1: A function to stand in for a hypothetical
37calculation that takes about 2 seconds to run</span>
38
39Next is the `main` function, which contains the parts of the workout app
40important for this example. This function represents the code that the app will
41call when a user asks for a workout plan. Because the interaction with the
42app’s frontend isn’t relevant to the use of closures, we’ll hardcode values
43representing inputs to our program and print the outputs.
44
45The required inputs are these:
46
47* An intensity number from the user, which is specified when they request
48 a workout to indicate whether they want a low-intensity workout or a
49 high-intensity workout
50* A random number that will generate some variety in the workout plans
51
52The output will be the recommended workout plan. Listing 13-2 shows the `main`
9fa01778 53function we’ll use.
13cf67c4
XL
54
55<span class="filename">Filename: src/main.rs</span>
56
57```rust
74b04a01 58{{#rustdoc_include ../listings/ch13-functional-features/listing-13-02/src/main.rs:here}}
13cf67c4
XL
59```
60
61<span class="caption">Listing 13-2: A `main` function with hardcoded values to
62simulate user input and random number generation</span>
63
64We’ve hardcoded the variable `simulated_user_specified_value` as 10 and the
65variable `simulated_random_number` as 7 for simplicity’s sake; in an actual
66program, we’d get the intensity number from the app frontend, and we’d use the
67`rand` crate to generate a random number, as we did in the Guessing Game
68example in Chapter 2. The `main` function calls a `generate_workout` function
69with the simulated input values.
70
71Now that we have the context, let’s get to the algorithm. The function
72`generate_workout` in Listing 13-3 contains the business logic of the
73app that we’re most concerned with in this example. The rest of the code
74changes in this example will be made to this function.
75
76<span class="filename">Filename: src/main.rs</span>
77
78```rust
74b04a01 79{{#rustdoc_include ../listings/ch13-functional-features/listing-13-03/src/main.rs:here}}
13cf67c4
XL
80```
81
82<span class="caption">Listing 13-3: The business logic that prints the workout
83plans based on the inputs and calls to the `simulated_expensive_calculation`
84function</span>
85
86The code in Listing 13-3 has multiple calls to the slow calculation function.
87The first `if` block calls `simulated_expensive_calculation` twice, the `if`
88inside the outer `else` doesn’t call it at all, and the code inside the
89second `else` case calls it once.
90
13cf67c4 91The desired behavior of the `generate_workout` function is to first check
e74abb32
XL
92whether the user wants a low-intensity workout (indicated by a number less than
9325) or a high-intensity workout (a number of 25 or greater).
13cf67c4
XL
94
95Low-intensity workout plans will recommend a number of push-ups and sit-ups
96based on the complex algorithm we’re simulating.
97
98If the user wants a high-intensity workout, there’s some additional logic: if
99the value of the random number generated by the app happens to be 3, the app
100will recommend a break and hydration. If not, the user will get a number of
101minutes of running based on the complex algorithm.
102
103This code works the way the business wants it to now, but let’s say the data
104science team decides that we need to make some changes to the way we call the
105`simulated_expensive_calculation` function in the future. To simplify the
106update when those changes happen, we want to refactor this code so it calls the
107`simulated_expensive_calculation` function only once. We also want to cut the
108place where we’re currently unnecessarily calling the function twice without
109adding any other calls to that function in the process. That is, we don’t want
110to call it if the result isn’t needed, and we still want to call it only once.
111
112#### Refactoring Using Functions
113
114We could restructure the workout program in many ways. First, we’ll try
115extracting the duplicated call to the `simulated_expensive_calculation`
9fa01778 116function into a variable, as shown in Listing 13-4.
13cf67c4
XL
117
118<span class="filename">Filename: src/main.rs</span>
119
120```rust
74b04a01 121{{#rustdoc_include ../listings/ch13-functional-features/listing-13-04/src/main.rs:here}}
13cf67c4
XL
122```
123
124<span class="caption">Listing 13-4: Extracting the calls to
125`simulated_expensive_calculation` to one place and storing the result in the
126`expensive_result` variable</span>
127
128This change unifies all the calls to `simulated_expensive_calculation` and
129solves the problem of the first `if` block unnecessarily calling the function
130twice. Unfortunately, we’re now calling this function and waiting for the
131result in all cases, which includes the inner `if` block that doesn’t use the
132result value at all.
133
6a06907d
XL
134We want to refer to `simulated_expensive_calculation` only once in
135`generate_workout`, but defer the expensive calculation to only where
136we actually need the result. This is a use case for closures!
13cf67c4
XL
137
138#### Refactoring with Closures to Store Code
139
140Instead of always calling the `simulated_expensive_calculation` function before
141the `if` blocks, we can define a closure and store the *closure* in a variable
142rather than storing the result of the function call, as shown in Listing 13-5.
143We can actually move the whole body of `simulated_expensive_calculation` within
9fa01778 144the closure we’re introducing here.
13cf67c4
XL
145
146<span class="filename">Filename: src/main.rs</span>
147
148```rust
74b04a01 149{{#rustdoc_include ../listings/ch13-functional-features/listing-13-05/src/main.rs:here}}
13cf67c4
XL
150```
151
152<span class="caption">Listing 13-5: Defining a closure and storing it in the
153`expensive_closure` variable</span>
154
155The closure definition comes after the `=` to assign it to the variable
156`expensive_closure`. To define a closure, we start with a pair of vertical
157pipes (`|`), inside which we specify the parameters to the closure; this syntax
158was chosen because of its similarity to closure definitions in Smalltalk and
159Ruby. This closure has one parameter named `num`: if we had more than one
160parameter, we would separate them with commas, like `|param1, param2|`.
161
162After the parameters, we place curly brackets that hold the body of the
163closure—these are optional if the closure body is a single expression. The end
164of the closure, after the curly brackets, needs a semicolon to complete the
165`let` statement. The value returned from the last line in the closure body
166(`num`) will be the value returned from the closure when it’s called, because
9fa01778 167that line doesn’t end in a semicolon; just as in function bodies.
13cf67c4
XL
168
169Note that this `let` statement means `expensive_closure` contains the
170*definition* of an anonymous function, not the *resulting value* of calling the
171anonymous function. Recall that we’re using a closure because we want to define
172the code to call at one point, store that code, and call it at a later point;
173the code we want to call is now stored in `expensive_closure`.
174
175With the closure defined, we can change the code in the `if` blocks to call the
176closure to execute the code and get the resulting value. We call a closure like
177we do a function: we specify the variable name that holds the closure
178definition and follow it with parentheses containing the argument values we
9fa01778 179want to use, as shown in Listing 13-6.
13cf67c4
XL
180
181<span class="filename">Filename: src/main.rs</span>
182
183```rust
74b04a01 184{{#rustdoc_include ../listings/ch13-functional-features/listing-13-06/src/main.rs:here}}
13cf67c4
XL
185```
186
187<span class="caption">Listing 13-6: Calling the `expensive_closure` we’ve
188defined</span>
189
6a06907d
XL
190Now how to perform the expensive calculation is defined in only one
191place, and we’re only executing that code where we need the results.
13cf67c4
XL
192
193However, we’ve reintroduced one of the problems from Listing 13-3: we’re still
194calling the closure twice in the first `if` block, which will call the
195expensive code twice and make the user wait twice as long as they need to. We
196could fix this problem by creating a variable local to that `if` block to hold
197the result of calling the closure, but closures provide us with another
198solution. We’ll talk about that solution in a bit. But first let’s talk about
199why there aren’t type annotations in the closure definition and the traits
200involved with closures.
201
202### Closure Type Inference and Annotation
203
204Closures don’t require you to annotate the types of the parameters or the
205return value like `fn` functions do. Type annotations are required on functions
206because they’re part of an explicit interface exposed to your users. Defining
207this interface rigidly is important for ensuring that everyone agrees on what
208types of values a function uses and returns. But closures aren’t used in an
209exposed interface like this: they’re stored in variables and used without
210naming them and exposing them to users of our library.
211
212Closures are usually short and relevant only within a narrow context rather
213than in any arbitrary scenario. Within these limited contexts, the compiler is
214reliably able to infer the types of the parameters and the return type, similar
215to how it’s able to infer the types of most variables.
216
217Making programmers annotate the types in these small, anonymous functions would
218be annoying and largely redundant with the information the compiler already has
219available.
220
221As with variables, we can add type annotations if we want to increase
222explicitness and clarity at the cost of being more verbose than is strictly
223necessary. Annotating the types for the closure we defined in Listing 13-5
9fa01778 224would look like the definition shown in Listing 13-7.
13cf67c4
XL
225
226<span class="filename">Filename: src/main.rs</span>
227
228```rust
74b04a01 229{{#rustdoc_include ../listings/ch13-functional-features/listing-13-07/src/main.rs:here}}
13cf67c4
XL
230```
231
232<span class="caption">Listing 13-7: Adding optional type annotations of the
233parameter and return value types in the closure</span>
234
235With type annotations added, the syntax of closures looks more similar to the
236syntax of functions. The following is a vertical comparison of the syntax for
237the definition of a function that adds 1 to its parameter and a closure that
238has the same behavior. We’ve added some spaces to line up the relevant parts.
239This illustrates how closure syntax is similar to function syntax except for
240the use of pipes and the amount of syntax that is optional:
241
242```rust,ignore
243fn add_one_v1 (x: u32) -> u32 { x + 1 }
244let add_one_v2 = |x: u32| -> u32 { x + 1 };
245let add_one_v3 = |x| { x + 1 };
246let add_one_v4 = |x| x + 1 ;
247```
248
249The first line shows a function definition, and the second line shows a fully
250annotated closure definition. The third line removes the type annotations from
251the closure definition, and the fourth line removes the brackets, which are
252optional because the closure body has only one expression. These are all valid
74b04a01
XL
253definitions that will produce the same behavior when they’re called. Calling
254the closures is required for `add_one_v3` and `add_one_v4` to be able to
255compile because the types will be inferred from their usage.
13cf67c4
XL
256
257Closure definitions will have one concrete type inferred for each of their
258parameters and for their return value. For instance, Listing 13-8 shows the
259definition of a short closure that just returns the value it receives as a
260parameter. This closure isn’t very useful except for the purposes of this
261example. Note that we haven’t added any type annotations to the definition: if
262we then try to call the closure twice, using a `String` as an argument the
263first time and a `u32` the second time, we’ll get an error.
264
265<span class="filename">Filename: src/main.rs</span>
266
267```rust,ignore,does_not_compile
74b04a01 268{{#rustdoc_include ../listings/ch13-functional-features/listing-13-08/src/main.rs:here}}
13cf67c4
XL
269```
270
271<span class="caption">Listing 13-8: Attempting to call a closure whose types
272are inferred with two different types</span>
273
274The compiler gives us this error:
275
f035d41b 276```console
74b04a01 277{{#include ../listings/ch13-functional-features/listing-13-08/output.txt}}
13cf67c4
XL
278```
279
280The first time we call `example_closure` with the `String` value, the compiler
281infers the type of `x` and the return type of the closure to be `String`. Those
5869c6ff 282types are then locked into the closure in `example_closure`, and we get a type
13cf67c4
XL
283error if we try to use a different type with the same closure.
284
285### Storing Closures Using Generic Parameters and the `Fn` Traits
286
287Let’s return to our workout generation app. In Listing 13-6, our code was still
288calling the expensive calculation closure more times than it needed to. One
289option to solve this issue is to save the result of the expensive closure in a
290variable for reuse and use the variable in each place we need the result,
291instead of calling the closure again. However, this method could result in a
292lot of repeated code.
293
294Fortunately, another solution is available to us. We can create a struct that
295will hold the closure and the resulting value of calling the closure. The
296struct will execute the closure only if we need the resulting value, and it
297will cache the resulting value so the rest of our code doesn’t have to be
298responsible for saving and reusing the result. You may know this pattern as
299*memoization* or *lazy evaluation*.
300
301To make a struct that holds a closure, we need to specify the type of the
302closure, because a struct definition needs to know the types of each of its
303fields. Each closure instance has its own unique anonymous type: that is, even
304if two closures have the same signature, their types are still considered
305different. To define structs, enums, or function parameters that use closures,
306we use generics and trait bounds, as we discussed in Chapter 10.
307
308The `Fn` traits are provided by the standard library. All closures implement at
309least one of the traits: `Fn`, `FnMut`, or `FnOnce`. We’ll discuss the
9fa01778
XL
310difference between these traits in the [“Capturing the Environment with
311Closures”](#capturing-the-environment-with-closures)<!-- ignore --> section; in
312this example, we can use the `Fn` trait.
13cf67c4
XL
313
314We add types to the `Fn` trait bound to represent the types of the parameters
315and return values the closures must have to match this trait bound. In this
316case, our closure has a parameter of type `u32` and returns a `u32`, so the
317trait bound we specify is `Fn(u32) -> u32`.
318
319Listing 13-9 shows the definition of the `Cacher` struct that holds a closure
9fa01778 320and an optional result value.
13cf67c4
XL
321
322<span class="filename">Filename: src/main.rs</span>
323
324```rust
74b04a01 325{{#rustdoc_include ../listings/ch13-functional-features/listing-13-09/src/main.rs:here}}
13cf67c4
XL
326```
327
328<span class="caption">Listing 13-9: Defining a `Cacher` struct that holds a
329closure in `calculation` and an optional result in `value`</span>
330
331The `Cacher` struct has a `calculation` field of the generic type `T`. The
332trait bounds on `T` specify that it’s a closure by using the `Fn` trait. Any
333closure we want to store in the `calculation` field must have one `u32`
334parameter (specified within the parentheses after `Fn`) and must return a
335`u32` (specified after the `->`).
336
337> Note: Functions can implement all three of the `Fn` traits too. If what we
338> want to do doesn’t require capturing a value from the environment, we can use
339> a function rather than a closure where we need something that implements an
340> `Fn` trait.
341
342The `value` field is of type `Option<u32>`. Before we execute the closure,
343`value` will be `None`. When code using a `Cacher` asks for the *result* of the
344closure, the `Cacher` will execute the closure at that time and store the
345result within a `Some` variant in the `value` field. Then if the code asks for
346the result of the closure again, instead of executing the closure again, the
347`Cacher` will return the result held in the `Some` variant.
348
349The logic around the `value` field we’ve just described is defined in Listing
9fa01778 35013-10.
13cf67c4
XL
351
352<span class="filename">Filename: src/main.rs</span>
353
354```rust
74b04a01 355{{#rustdoc_include ../listings/ch13-functional-features/listing-13-10/src/main.rs:here}}
13cf67c4
XL
356```
357
358<span class="caption">Listing 13-10: The caching logic of `Cacher`</span>
359
360We want `Cacher` to manage the struct fields’ values rather than letting the
361calling code potentially change the values in these fields directly, so these
362fields are private.
363
364The `Cacher::new` function takes a generic parameter `T`, which we’ve defined
365as having the same trait bound as the `Cacher` struct. Then `Cacher::new`
366returns a `Cacher` instance that holds the closure specified in the
367`calculation` field and a `None` value in the `value` field, because we haven’t
368executed the closure yet.
369
370When the calling code needs the result of evaluating the closure, instead of
371calling the closure directly, it will call the `value` method. This method
372checks whether we already have a resulting value in `self.value` in a `Some`;
373if we do, it returns the value within the `Some` without executing the closure
374again.
375
376If `self.value` is `None`, the code calls the closure stored in
377`self.calculation`, saves the result in `self.value` for future use, and
378returns the value as well.
379
380Listing 13-11 shows how we can use this `Cacher` struct in the function
9fa01778 381`generate_workout` from Listing 13-6.
13cf67c4
XL
382
383<span class="filename">Filename: src/main.rs</span>
384
385```rust
74b04a01 386{{#rustdoc_include ../listings/ch13-functional-features/listing-13-11/src/main.rs:here}}
13cf67c4
XL
387```
388
389<span class="caption">Listing 13-11: Using `Cacher` in the `generate_workout`
390function to abstract away the caching logic</span>
391
392Instead of saving the closure in a variable directly, we save a new instance of
393`Cacher` that holds the closure. Then, in each place we want the result, we
394call the `value` method on the `Cacher` instance. We can call the `value`
395method as many times as we want, or not call it at all, and the expensive
396calculation will be run a maximum of once.
397
398Try running this program with the `main` function from Listing 13-2. Change the
399values in the `simulated_user_specified_value` and `simulated_random_number`
400variables to verify that in all the cases in the various `if` and `else`
401blocks, `calculating slowly...` appears only once and only when needed. The
402`Cacher` takes care of the logic necessary to ensure we aren’t calling the
403expensive calculation more than we need to so `generate_workout` can focus on
404the business logic.
405
406### Limitations of the `Cacher` Implementation
407
408Caching values is a generally useful behavior that we might want to use in
409other parts of our code with different closures. However, there are two
410problems with the current implementation of `Cacher` that would make reusing it
411in different contexts difficult.
412
413The first problem is that a `Cacher` instance assumes it will always get the
414same value for the parameter `arg` to the `value` method. That is, this test of
415`Cacher` will fail:
416
417```rust,ignore,panics
74b04a01 418{{#rustdoc_include ../listings/ch13-functional-features/no-listing-01-failing-cacher-test/src/lib.rs:here}}
13cf67c4
XL
419```
420
421This test creates a new `Cacher` instance with a closure that returns the value
422passed into it. We call the `value` method on this `Cacher` instance with an
423`arg` value of 1 and then an `arg` value of 2, and we expect the call to
9fa01778 424`value` with the `arg` value of 2 to return 2.
13cf67c4
XL
425
426Run this test with the `Cacher` implementation in Listing 13-9 and Listing
42713-10, and the test will fail on the `assert_eq!` with this message:
428
f035d41b 429```console
74b04a01 430{{#include ../listings/ch13-functional-features/no-listing-01-failing-cacher-test/output.txt}}
13cf67c4
XL
431```
432
433The problem is that the first time we called `c.value` with 1, the `Cacher`
5869c6ff
XL
434instance saved `Some(1)` in `self.value`. Thereafter, no matter what we pass into
435the `value` method, it will always return 1.
13cf67c4
XL
436
437Try modifying `Cacher` to hold a hash map rather than a single value. The keys
438of the hash map will be the `arg` values that are passed in, and the values of
439the hash map will be the result of calling the closure on that key. Instead of
440looking at whether `self.value` directly has a `Some` or a `None` value, the
441`value` function will look up the `arg` in the hash map and return the value if
442it’s present. If it’s not present, the `Cacher` will call the closure and save
443the resulting value in the hash map associated with its `arg` value.
444
445The second problem with the current `Cacher` implementation is that it only
446accepts closures that take one parameter of type `u32` and return a `u32`. We
447might want to cache the results of closures that take a string slice and return
448`usize` values, for example. To fix this issue, try introducing more generic
449parameters to increase the flexibility of the `Cacher` functionality.
450
451### Capturing the Environment with Closures
452
453In the workout generator example, we only used closures as inline anonymous
454functions. However, closures have an additional capability that functions don’t
455have: they can capture their environment and access variables from the scope in
456which they’re defined.
457
458Listing 13-12 has an example of a closure stored in the `equal_to_x` variable
9fa01778 459that uses the `x` variable from the closure’s surrounding environment.
13cf67c4
XL
460
461<span class="filename">Filename: src/main.rs</span>
462
463```rust
74b04a01 464{{#rustdoc_include ../listings/ch13-functional-features/listing-13-12/src/main.rs}}
13cf67c4
XL
465```
466
467<span class="caption">Listing 13-12: Example of a closure that refers to a
468variable in its enclosing scope</span>
469
470Here, even though `x` is not one of the parameters of `equal_to_x`, the
471`equal_to_x` closure is allowed to use the `x` variable that’s defined in the
472same scope that `equal_to_x` is defined in.
473
474We can’t do the same with functions; if we try with the following example, our
475code won’t compile:
476
477<span class="filename">Filename: src/main.rs</span>
478
479```rust,ignore,does_not_compile
74b04a01 480{{#rustdoc_include ../listings/ch13-functional-features/no-listing-02-functions-cant-capture/src/main.rs}}
13cf67c4
XL
481```
482
483We get an error:
484
f035d41b 485```console
74b04a01 486{{#include ../listings/ch13-functional-features/no-listing-02-functions-cant-capture/output.txt}}
13cf67c4
XL
487```
488
489The compiler even reminds us that this only works with closures!
490
491When a closure captures a value from its environment, it uses memory to store
492the values for use in the closure body. This use of memory is overhead that we
493don’t want to pay in more common cases where we want to execute code that
494doesn’t capture its environment. Because functions are never allowed to capture
495their environment, defining and using functions will never incur this overhead.
496
497Closures can capture values from their environment in three ways, which
498directly map to the three ways a function can take a parameter: taking
499ownership, borrowing mutably, and borrowing immutably. These are encoded in the
500three `Fn` traits as follows:
501
502* `FnOnce` consumes the variables it captures from its enclosing scope, known
503 as the closure’s *environment*. To consume the captured variables, the
504 closure must take ownership of these variables and move them into the closure
505 when it is defined. The `Once` part of the name represents the fact that the
506 closure can’t take ownership of the same variables more than once, so it can
507 be called only once.
508* `FnMut` can change the environment because it mutably borrows values.
509* `Fn` borrows values from the environment immutably.
510
511When you create a closure, Rust infers which trait to use based on how the
512closure uses the values from the environment. All closures implement `FnOnce`
513because they can all be called at least once. Closures that don’t move the
514captured variables also implement `FnMut`, and closures that don’t need mutable
515access to the captured variables also implement `Fn`. In Listing 13-12, the
516`equal_to_x` closure borrows `x` immutably (so `equal_to_x` has the `Fn` trait)
517because the body of the closure only needs to read the value in `x`.
518
519If you want to force the closure to take ownership of the values it uses in the
520environment, you can use the `move` keyword before the parameter list. This
521technique is mostly useful when passing a closure to a new thread to move the
522data so it’s owned by the new thread.
523
fc512014
XL
524> Note: `move` closures may still implement `Fn` or `FnMut`, even though
525> they capture variables by move. This is because the traits implemented by a
526> closure type are determined by what the closure does with captured values,
527> not how it captures them. The `move` keyword only specifies the latter.
528
13cf67c4
XL
529We’ll have more examples of `move` closures in Chapter 16 when we talk about
530concurrency. For now, here’s the code from Listing 13-12 with the `move`
531keyword added to the closure definition and using vectors instead of integers,
532because integers can be copied rather than moved; note that this code will not
533yet compile.
534
535<span class="filename">Filename: src/main.rs</span>
536
537```rust,ignore,does_not_compile
74b04a01 538{{#rustdoc_include ../listings/ch13-functional-features/no-listing-03-move-closures/src/main.rs}}
13cf67c4
XL
539```
540
541We receive the following error:
542
f035d41b 543```console
74b04a01 544{{#include ../listings/ch13-functional-features/no-listing-03-move-closures/output.txt}}
13cf67c4
XL
545```
546
547The `x` value is moved into the closure when the closure is defined, because we
548added the `move` keyword. The closure then has ownership of `x`, and `main`
549isn’t allowed to use `x` anymore in the `println!` statement. Removing
550`println!` will fix this example.
551
552Most of the time when specifying one of the `Fn` trait bounds, you can start
553with `Fn` and the compiler will tell you if you need `FnMut` or `FnOnce` based
554on what happens in the closure body.
555
556To illustrate situations where closures that can capture their environment are
557useful as function parameters, let’s move on to our next topic: iterators.