]> git.lizzy.rs Git - rust.git/blob - src/doc/trpl/closures.md
Rollup merge of #21357 - kimroen:patch-1, r=sanxiyn
[rust.git] / src / doc / trpl / closures.md
1 % Closures
2
3 So far, we've made lots of functions in Rust, but we've given them all names.
4 Rust also allows us to create anonymous functions. Rust's anonymous
5 functions are called *closures*. By themselves, closures aren't all that
6 interesting, but when you combine them with functions that take closures as
7 arguments, really powerful things are possible.
8
9 Let's make a closure:
10
11 ```{rust}
12 let add_one = |&: x| { 1 + x };
13
14 println!("The sum of 5 plus 1 is {}.", add_one(5));
15 ```
16
17 We create a closure using the `|...| { ... }` syntax, and then we create a
18 binding so we can use it later. Note that we call the function using the
19 binding name and two parentheses, just like we would for a named function.
20
21 Let's compare syntax. The two are pretty close:
22
23 ```{rust}
24 let add_one = |&: x: i32| -> i32 { 1 + x };
25 fn  add_one      (x: i32) -> i32 { 1 + x }
26 ```
27
28 As you may have noticed, closures infer their argument and return types, so you
29 don't need to declare one. This is different from named functions, which
30 default to returning unit (`()`).
31
32 There's one big difference between a closure and named functions, and it's in
33 the name: a closure "closes over its environment." What does that mean? It means
34 this:
35
36 ```{rust}
37 fn main() {
38     let x: i32 = 5;
39
40     let printer = |&:| { println!("x is: {}", x); };
41
42     printer(); // prints "x is: 5"
43 }
44 ```
45
46 The `||` syntax means this is an anonymous closure that takes no arguments.
47 Without it, we'd just have a block of code in `{}`s.
48
49 In other words, a closure has access to variables in the scope where it's
50 defined. The closure borrows any variables it uses, so this will error:
51
52 ```{rust,ignore}
53 fn main() {
54     let mut x: i32 = 5;
55
56     let printer = |&:| { println!("x is: {}", x); };
57
58     x = 6; // error: cannot assign to `x` because it is borrowed
59 }
60 ```
61
62 ## Moving closures
63
64 Rust has a second type of closure, called a *moving closure*. Moving
65 closures are indicated using the `move` keyword (e.g., `move || x *
66 x`). The difference between a moving closure and an ordinary closure
67 is that a moving closure always takes ownership of all variables that
68 it uses. Ordinary closures, in contrast, just create a reference into
69 the enclosing stack frame. Moving closures are most useful with Rust's
70 concurrency features, and so we'll just leave it at this for
71 now. We'll talk about them more in the "Threads" section of the guide.
72
73 ## Accepting closures as arguments
74
75 Closures are most useful as an argument to another function. Here's an example:
76
77 ```{rust}
78 fn twice<F: Fn(i32) -> i32>(x: i32, f: F) -> i32 {
79     f(x) + f(x)
80 }
81
82 fn main() {
83     let square = |&: x: i32| { x * x };
84
85     twice(5, square); // evaluates to 50
86 }
87 ```
88
89 Let's break the example down, starting with `main`:
90
91 ```{rust}
92 let square = |&: x: i32| { x * x };
93 ```
94
95 We've seen this before. We make a closure that takes an integer, and returns
96 its square.
97
98 ```{rust}
99 # fn twice<F: Fn(i32) -> i32>(x: i32, f: F) -> i32 { f(x) + f(x) }
100 # let square = |&: x: i32| { x * x };
101 twice(5, square); // evaluates to 50
102 ```
103
104 This line is more interesting. Here, we call our function, `twice`, and we pass
105 it two arguments: an integer, `5`, and our closure, `square`. This is just like
106 passing any other two variable bindings to a function, but if you've never
107 worked with closures before, it can seem a little complex. Just think: "I'm
108 passing two variables: one is an i32, and one is a function."
109
110 Next, let's look at how `twice` is defined:
111
112 ```{rust,ignore}
113 fn twice<F: Fn(i32) -> i32>(x: i32, f: F) -> i32 {
114 ```
115
116 `twice` takes two arguments, `x` and `f`. That's why we called it with two
117 arguments. `x` is an `i32`, we've done that a ton of times. `f` is a function,
118 though, and that function takes an `i32` and returns an `i32`. This is
119 what the requirement `Fn(i32) -> i32` for the type parameter `F` says.
120 You might ask yourself: why do we need to introduce a type parameter here?
121 That is because in Rust each closure has its own unique type.
122 So, not only do closures with different signatures have different types,
123 but different closures with the *same* signature have *different* types!
124 You can think of it this way: the behaviour of a closure is part of its type.
125 And since we want to support many different closures that all take
126 an `i32` and return an `i32` we introduced a type parameter that is able
127 to represent all these closures. 
128
129 This is the most complicated function signature we've seen yet! Give it a read
130 a few times until you can see how it works. It takes a teeny bit of practice, and
131 then it's easy. The good news is that this kind of passing a closure around
132 can be very efficient. With all the type information available at compile-time
133 the compiler can do wonders.
134
135 Finally, `twice` returns an `i32` as well.
136
137 Okay, let's look at the body of `twice`:
138
139 ```{rust}
140 fn twice<F: Fn(i32) -> i32>(x: i32, f: F) -> i32 {
141   f(x) + f(x)
142 }
143 ```
144
145 Since our closure is named `f`, we can call it just like we called our closures
146 before, and we pass in our `x` argument to each one, hence the name `twice`.
147
148 If you do the math, `(5 * 5) + (5 * 5) == 50`, so that's the output we get.
149
150 Play around with this concept until you're comfortable with it. Rust's standard
151 library uses lots of closures where appropriate, so you'll be using
152 this technique a lot.
153
154 If we didn't want to give `square` a name, we could just define it inline.
155 This example is the same as the previous one:
156
157 ```{rust}
158 fn twice<F: Fn(i32) -> i32>(x: i32, f: F) -> i32 {
159     f(x) + f(x)
160 }
161
162 fn main() {
163     twice(5, |x: i32| { x * x }); // evaluates to 50
164 }
165 ```
166
167 A named function's name can be used wherever you'd use a closure. Another
168 way of writing the previous example:
169
170 ```{rust}
171 fn twice<F: Fn(i32) -> i32>(x: i32, f: F) -> i32 {
172     f(x) + f(x)
173 }
174
175 fn square(x: i32) -> i32 { x * x }
176
177 fn main() {
178     twice(5, square); // evaluates to 50
179 }
180 ```
181
182 Doing this is not particularly common, but it's useful every once in a while.
183
184 That's all you need to get the hang of closures! Closures are a little bit
185 strange at first, but once you're used to them, you'll miss them
186 in other languages. Passing functions to other functions is
187 incredibly powerful, as you will see in the following chapter about iterators.