about summary refs log tree commit diff
diff options
context:
space:
mode:
authorJONNALAGADDA Srinivas <js@ojuslabs.com>2015-01-13 10:14:18 +0530
committerJONNALAGADDA Srinivas <js@ojuslabs.com>2015-01-13 10:14:18 +0530
commitac110df0ff52c3ae93d98bc75ec08b99d7d205b5 (patch)
tree0a2e4d58ca37e712d0c05855780810e123d27d6a
parent3d5fbae33897a8340542f21b6ded913148ca9199 (diff)
downloadrust-ac110df0ff52c3ae93d98bc75ec08b99d7d205b5.tar.gz
rust-ac110df0ff52c3ae93d98bc75ec08b99d7d205b5.zip
Expand the section on closures in TRPL.
* Include an illustration of a function that accepts two closures.
-rw-r--r--src/doc/trpl/closures.md43
1 files changed, 35 insertions, 8 deletions
diff --git a/src/doc/trpl/closures.md b/src/doc/trpl/closures.md
index 5b49df92fe3..3f78e0151bc 100644
--- a/src/doc/trpl/closures.md
+++ b/src/doc/trpl/closures.md
@@ -117,14 +117,7 @@ fn twice<F: Fn(i32) -> i32>(x: i32, f: F) -> i32 {
 arguments. `x` is an `i32`, we've done that a ton of times. `f` is a function,
 though, and that function takes an `i32` and returns an `i32`. This is
 what the requirement `Fn(i32) -> i32` for the type parameter `F` says.
-You might ask yourself: why do we need to introduce a type parameter here?
-That is because in Rust each closure has its own unique type.
-So, not only do closures with different signatures have different types,
-but different closures with the *same* signature have *different* types!
-You can think of it this way: the behaviour of a closure is part of its type.
-And since we want to support many different closures that all take
-an `i32` and return an `i32` we introduced a type parameter that is able
-to represent all these closures. 
+Now `F` represents *any* function that takes an `i32` and returns an `i32`.
 
 This is the most complicated function signature we've seen yet! Give it a read
 a few times until you can see how it works. It takes a teeny bit of practice, and
@@ -181,6 +174,40 @@ fn main() {
 
 Doing this is not particularly common, but it's useful every once in a while.
 
+Before we move on, let us look at a function that accepts two closures.
+
+```{rust}
+fn compose<F, G>(x: i32, f: F, g: G) -> i32
+    where F: Fn(i32) -> i32, G: Fn(i32) -> i32 {
+    g(f(x))
+}
+
+fn main() {
+    compose(5,
+            |&: n: i32| { n + 42 },
+            |&: n: i32| { n * 2 }); // evaluates to 94
+}
+```
+
+You might ask yourself: why do we need to introduce two type
+parameters `F` and `G` here?  Evidently, both `f` and `g` have the
+same signature: `Fn(i32) -> i32`.
+
+That is because in Rust each closure has its own unique type.
+So, not only do closures with different signatures have different types,
+but different closures with the *same* signature have *different*
+types, as well!
+
+You can think of it this way: the behavior of a closure is part of its
+type.  Therefore, using a single type parameter for both closures
+will accept the first of them, rejecting the second. The distinct
+type of the second closure does not allow it to be represented by the
+same type parameter as that of the first.  We acknowledge this, and
+use two different type parameters `F` and `G`.
+
+This also introduces the `where` clause, which lets us describe type
+parameters in a more flexible manner.
+
 That's all you need to get the hang of closures! Closures are a little bit
 strange at first, but once you're used to them, you'll miss them
 in other languages. Passing functions to other functions is