@@ -117,14 +117,7 @@ fn twice<F: Fn(i32) -> i32>(x: i32, f: F) -> i32 {
117117arguments. ` x ` is an ` i32 ` , we've done that a ton of times. ` f ` is a function,
118118though, and that function takes an ` i32 ` and returns an ` i32 ` . This is
119119what 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 ` .
128121
129122This is the most complicated function signature we've seen yet! Give it a read
130123a few times until you can see how it works. It takes a teeny bit of practice, and
@@ -181,6 +174,40 @@ fn main() {
181174
182175Doing this is not particularly common, but it's useful every once in a while.
183176
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+
184211That's all you need to get the hang of closures! Closures are a little bit
185212strange at first, but once you're used to them, you'll miss them
186213in other languages. Passing functions to other functions is
0 commit comments