@@ -117,14 +117,7 @@ fn twice<F: Fn(i32) -> i32>(x: i32, f: F) -> i32 {
117
117
arguments. ` x ` is an ` i32 ` , we've done that a ton of times. ` f ` is a function,
118
118
though, and that function takes an ` i32 ` and returns an ` i32 ` . This is
119
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.
120
+ Now ` F ` represents * any* function that takes an ` i32 ` and returns an ` i32 ` .
128
121
129
122
This is the most complicated function signature we've seen yet! Give it a read
130
123
a few times until you can see how it works. It takes a teeny bit of practice, and
@@ -181,6 +174,40 @@ fn main() {
181
174
182
175
Doing this is not particularly common, but it's useful every once in a while.
183
176
177
+ Before we move on, let us look at a function that accepts two closures.
178
+
179
+ ``` {rust}
180
+ fn compose<F, G>(x: i32, f: F, g: G) -> i32
181
+ where F: Fn(i32) -> i32, G: Fn(i32) -> i32 {
182
+ g(f(x))
183
+ }
184
+
185
+ fn main() {
186
+ compose(5,
187
+ |&: n: i32| { n + 42 },
188
+ |&: n: i32| { n * 2 }); // evaluates to 94
189
+ }
190
+ ```
191
+
192
+ You might ask yourself: why do we need to introduce two type
193
+ parameters ` F ` and ` G ` here? Evidently, both ` f ` and ` g ` have the
194
+ same signature: ` Fn(i32) -> i32 ` .
195
+
196
+ That is because in Rust each closure has its own unique type.
197
+ So, not only do closures with different signatures have different types,
198
+ but different closures with the * same* signature have * different*
199
+ types, as well!
200
+
201
+ You can think of it this way: the behavior of a closure is part of its
202
+ type. Therefore, using a single type parameter for both closures
203
+ will accept the first of them, rejecting the second. The distinct
204
+ type of the second closure does not allow it to be represented by the
205
+ same type parameter as that of the first. We acknowledge this, and
206
+ use two different type parameters ` F ` and ` G ` .
207
+
208
+ This also introduces the ` where ` clause, which lets us describe type
209
+ parameters in a more flexible manner.
210
+
184
211
That's all you need to get the hang of closures! Closures are a little bit
185
212
strange at first, but once you're used to them, you'll miss them
186
213
in other languages. Passing functions to other functions is
0 commit comments