@@ -1723,59 +1723,72 @@ let x = 3;
17231723fn fun() -> () { println!("{}", x); }
17241724~~~~
17251725
1726- Rust also supports _closures_, functions that can access variables in
1727- the enclosing scope. Compare `x` in these:
1726+ A _closure_ does support accessing the enclosing scope; below we will create
1727+ 2 _closures_ (nameless functions). Compare how `||` replaces `()` and how
1728+ they try to access `x`:
17281729
1729- ~~~~
1730+ ~~~~ {.ignore}
17301731let x = 3;
17311732
17321733// `fun` is an invalid definition
1733- fn fun () -> () { println!("{}", x) }; // cannot reach enclosing scope
1734- let closure = || -> () { println!("{}", x) }; // can reach enclosing scope
1734+ fn fun () -> () { println!("{}", x) }; // cannot capture enclosing scope
1735+ let closure = || -> () { println!("{}", x) }; // can capture enclosing scope
17351736
1736- fun(); // Still won't work
1737- closure(); // Prints: 3
1738- ~~~~
1737+ // `fun_arg` is an invalid definition
1738+ fn fun_arg (arg: int) -> () { println!("{}", arg + x) }; // cannot capture enclosing scope
1739+ let closure_arg = |arg: int| -> () { println!("{}", arg + x) }; // Can capture enclosing scope
1740+ // ^
1741+ // Requires a type because the implementation needs to know which `+` to use.
1742+ // In the future, the implementation may not need the help.
17391743
1740- Closures can be utilized in this fashion:
1744+ fun(); // Still won't work
1745+ closure(); // Prints: 3
17411746
1747+ fun_arg(7); // Still won't work
1748+ closure_arg(7); // Prints: 10
17421749~~~~
1743- // Create a nameless function and assign it to `closure`. It's sole
1744- // argument is a yet unknown `x` to be supplied by the caller.
1745- let closure = |x| -> () { println!("{}", x) };
17461750
1747- // Define `call_closure_with_ten` to take one argument and return null `()`.
1748- // `fun` is a function which takes one `int` argument `|int|` and also returns
1749- // null `()`. `|int|` defines the `fun` to be of type _closure_
1750- fn call_closure_with_ten(fun: |int| -> ()) -> () { fun(10); }
1751+ Closures begin with the argument list between vertical bars and are followed by
1752+ a single expression. Remember that a block, `{ <expr1>; <expr2>; ... }`, is
1753+ considered a single expression: it evaluates to the result of the last
1754+ expression it contains if that expression is not followed by a semicolon,
1755+ otherwise the block evaluates to `()`.
17511756
1752- // The caller supplies `10` to the closure
1753- // which prints out the value
1754- call_closure_with_ten(closure);
1755- ~~~~
1757+ Since a closure is an expression, the compiler can usually infer the argument and
1758+ return types; so they are often omitted. This is in contrast to a function which
1759+ is a declaration and _not_ an expression. Declarations require the types to be
1760+ specified and carry no inference. Compare:
17561761
1757- This can be simplified by removing null arguments:
1762+ ~~~~ {.ignore}
1763+ // `fun` cannot infer the type of `x` so it must be provided because it is a function.
1764+ fn fun (x: int) -> () { println!("{}", x) };
1765+ let closure = |x | -> () { println!("{}", x) };
17581766
1767+ fun(10); // Prints 10
1768+ closure(20); // Prints 20
1769+
1770+ fun("String"); // Error: wrong type
1771+ // Error: This type is different from when `x` was originally evaluated
1772+ closure("String");
17591773~~~~
1760- let closure = |x| println!("{}", x);
1761- fn call_closure_with_ten(fun: |int|) { fun(10); }
17621774
1763- call_closure_with_ten(closure);
1775+ The null arguments `()` are typically dropped so the end result
1776+ is more compact.
1777+
17641778~~~~
1779+ let closure = |x| { println!("{}", x) };
17651780
1766- Closures begin with the argument list between vertical bars and are followed by
1767- a single expression. Remember that a block, `{ <expr1>; <expr2>; ... }`, is
1768- considered a single expression: it evaluates to the result of the last
1769- expression it contains if that expression is not followed by a semicolon,
1770- otherwise the block evaluates to `()`.
1781+ closure(20); // Prints 20
1782+ ~~~~
17711783
1772- The types of the arguments are generally omitted, as is the return type,
1773- because the compiler can almost always infer them. In the rare case where the
1774- compiler needs assistance, though, the arguments and return types may be
1775- annotated.
1784+ Here, in the rare case where the compiler needs assistance,
1785+ the arguments and return types may be annotated.
17761786
17771787~~~~
17781788let square = |x: int| -> uint { (x * x) as uint };
1789+
1790+ println!("{}", square(20)); // 400
1791+ println!("{}", square(-20)); // 400
17791792~~~~
17801793
17811794There are several forms of closure, each with its own role. The most
0 commit comments