From 8e420e07d914a50ef279de60e6b3d303e82bfd72 Mon Sep 17 00:00:00 2001 From: Craig Hills Date: Mon, 5 Oct 2015 22:25:19 -0400 Subject: [PATCH] trpl: Clarify closure terminology This is to address issue #28803 --- src/doc/trpl/closures.md | 42 +++++++++++++++++++++------------------- src/llvm | 2 +- 2 files changed, 23 insertions(+), 21 deletions(-) diff --git a/src/doc/trpl/closures.md b/src/doc/trpl/closures.md index 983af4a0efe..85e74b083b4 100644 --- a/src/doc/trpl/closures.md +++ b/src/doc/trpl/closures.md @@ -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 -we’ll 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 we’ll see. # Syntax @@ -34,7 +35,7 @@ assert_eq!(4, plus_two(2)); ``` You’ll 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 don’t 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 they’re anonymous, and they don’t cause the kinds of error-at-a-distance -problems that inferring named function types can. +But we don’t 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 they’re anonymous, and they don’t 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. I’ve added spaces -here for easier comparison: +The second is that the syntax is similar, but a bit different. I’ve added +spaces here for easier comparison: ```rust fn plus_one_v1 (x: i32) -> i32 { x + 1 } @@ -63,8 +64,8 @@ Small differences, but they’re 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 @@ isn’t 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`. There’s one other key point here: because we’re bounding a generic with a trait, this will get monomorphized, and therefore, we’ll be doing static diff --git a/src/llvm b/src/llvm index 62ad301a240..2e9f0d21fe3 160000 --- a/src/llvm +++ b/src/llvm @@ -1 +1 @@ -Subproject commit 62ad301a2407a7aca50c1d5120c63597d676d29f +Subproject commit 2e9f0d21fe321849a4759a01fc28eae82ef196d6