trpl: Clarify closure terminology

This is to address issue #28803
This commit is contained in:
Craig Hills 2015-10-05 22:25:19 -04:00
parent 32a8567ea4
commit 8e420e07d9
No known key found for this signature in database
GPG key ID: E9D7131C3851CA20
2 changed files with 23 additions and 21 deletions

View file

@ -1,9 +1,10 @@
% Closures
Rust not only has named functions, but anonymous functions as well. Anonymous
functions that have an associated environment are called closures, because they
close over an environment. Rust has a really great implementation of them, as
well see.
Sometimes it is useful to wrap up a function and free variables for better
clarity and reuse. The _free variables_ that can be used come from the
enclosing scope and are "closed over" when used in the function. From this, we
get the name "closures" and Rust provides a really great implementation of
them, as well see.
# Syntax
@ -34,7 +35,7 @@ assert_eq!(4, plus_two(2));
```
Youll notice a few things about closures that are a bit different from regular
functions defined with `fn`. The first is that we did not need to
named functions defined with `fn`. The first is that we did not need to
annotate the types of arguments the closure takes or the values it returns. We
can:
@ -44,14 +45,14 @@ let plus_one = |x: i32| -> i32 { x + 1 };
assert_eq!(2, plus_one(1));
```
But we dont have to. Why is this? Basically, it was chosen for ergonomic reasons.
While specifying the full type for named functions is helpful with things like
documentation and type inference, the types of closures are rarely documented
since theyre anonymous, and they dont cause the kinds of error-at-a-distance
problems that inferring named function types can.
But we dont have to. Why is this? Basically, it was chosen for ergonomic
reasons. While specifying the full type for named functions is helpful with
things like documentation and type inference, types within closures are rarely
documented since theyre anonymous, and they dont cause the kinds of
error-at-a-distance problems that inferring named function types can.
The second is that the syntax is similar, but a bit different. Ive added spaces
here for easier comparison:
The second is that the syntax is similar, but a bit different. Ive added
spaces here for easier comparison:
```rust
fn plus_one_v1 (x: i32) -> i32 { x + 1 }
@ -63,8 +64,8 @@ Small differences, but theyre similar.
# Closures and their environment
Closures are called such because they close over their environment. It
looks like this:
The environment for a closure can include bindings from it's enclosing scope in
addition to parameters and local bindings. It looks like this:
```rust
let num = 5;
@ -197,9 +198,10 @@ frame. Without `move`, a closure may be tied to the stack frame that created
it, while a `move` closure is self-contained. This means that you cannot
generally return a non-`move` closure from a function, for example.
But before we talk about taking and returning closures, we should talk some more
about the way that closures are implemented. As a systems language, Rust gives
you tons of control over what your code does, and closures are no different.
But before we talk about taking and returning closures, we should talk some
more about the way that closures are implemented. As a systems language, Rust
gives you tons of control over what your code does, and closures are no
different.
# Closure implementation
@ -288,9 +290,9 @@ isnt interesting. The next part is:
# some_closure(1) }
```
Because `Fn` is a trait, we can bound our generic with it. In this case, our closure
takes a `i32` as an argument and returns an `i32`, and so the generic bound we use
is `Fn(i32) -> i32`.
Because `Fn` is a trait, we can bound our generic with it. In this case, our
closure takes a `i32` as an argument and returns an `i32`, and so the generic
bound we use is `Fn(i32) -> i32`.
Theres one other key point here: because were bounding a generic with a
trait, this will get monomorphized, and therefore, well be doing static

@ -1 +1 @@
Subproject commit 62ad301a2407a7aca50c1d5120c63597d676d29f
Subproject commit 2e9f0d21fe321849a4759a01fc28eae82ef196d6