@@ -1720,38 +1720,103 @@ environment (sometimes referred to as "capturing" variables in their
17201720environment). For example, you couldn't write the following:
17211721
17221722~~~~ {.ignore}
1723- let foo = 10 ;
1723+ let x = 3 ;
17241724
1725- fn bar() -> int {
1726- return foo; // `bar` cannot refer to `foo`
1727- }
1725+ // `fun` cannot refer to `x`
1726+ fn fun() -> () { println!("{}", x); }
17281727~~~~
17291728
1730- Rust also supports _closures_, functions that can access variables in
1731- the enclosing scope.
1729+ A _closure_ does support accessing the enclosing scope; below we will create
1730+ 2 _closures_ (nameless functions). Compare how `||` replaces `()` and how
1731+ they try to access `x`:
17321732
1733- ~~~~
1734- fn call_closure_with_ten(b: |int|) { b(10); }
1733+ ~~~~ {.ignore}
1734+ let x = 3;
17351735
1736- let captured_var = 20;
1737- let closure = |arg| println!("captured_var={}, arg={}", captured_var, arg);
1736+ // `fun` is an invalid definition
1737+ fn fun () -> () { println!("{}", x) } // cannot capture from enclosing scope
1738+ let closure = || -> () { println!("{}", x) }; // can capture from enclosing scope
17381739
1739- call_closure_with_ten(closure);
1740+ // `fun_arg` is an invalid definition
1741+ fn fun_arg (arg: int) -> () { println!("{}", arg + x) } // cannot capture
1742+ let closure_arg = |arg: int| -> () { println!("{}", arg + x) }; // can capture
1743+ // ^
1744+ // Requires a type because the implementation needs to know which `+` to use.
1745+ // In the future, the implementation may not need the help.
1746+
1747+ fun(); // Still won't work
1748+ closure(); // Prints: 3
1749+
1750+ fun_arg(7); // Still won't work
1751+ closure_arg(7); // Prints: 10
17401752~~~~
17411753
17421754Closures begin with the argument list between vertical bars and are followed by
17431755a single expression. Remember that a block, `{ <expr1>; <expr2>; ... }`, is
17441756considered a single expression: it evaluates to the result of the last
17451757expression it contains if that expression is not followed by a semicolon,
1746- otherwise the block evaluates to `()`.
1758+ otherwise the block evaluates to `()`, the unit value.
1759+
1760+ In general, return types and all argument types must be specified
1761+ explicitly for function definitions. (As previously mentioned in the
1762+ [Functions section](#functions), omitting the return type from a
1763+ function declaration is synonymous with an explicit declaration of
1764+ return type unit, `()`.)
1765+
1766+ ~~~~ {.ignore}
1767+ fn fun (x: int) { println!("{}", x) } // this is same as saying `-> ()`
1768+ fn square(x: int) -> uint { (x * x) as uint } // other return types are explicit
1769+
1770+ // Error: mismatched types: expected `()` but found `uint`
1771+ fn badfun(x: int) { (x * x) as uint }
1772+ ~~~~
1773+
1774+ On the other hand, the compiler can usually infer both the argument
1775+ and return types for a closure expression; therefore they are often
1776+ omitted, since both a human reader and the compiler can deduce the
1777+ types from the immediate context. This is in contrast to function
1778+ declarations, which require types to be specified and are not subject
1779+ to type inference. Compare:
17471780
1748- The types of the arguments are generally omitted, as is the return type,
1749- because the compiler can almost always infer them. In the rare case where the
1750- compiler needs assistance, though, the arguments and return types may be
1751- annotated.
1781+ ~~~~ {.ignore}
1782+ // `fun` as a function declaration cannot infer the type of `x`, so it must be provided
1783+ fn fun (x: int) { println!("{}", x) }
1784+ let closure = |x | { println!("{}", x) }; // infers `x: int`, return type `()`
1785+
1786+ // For closures, omitting a return type is *not* synonymous with `-> ()`
1787+ let add_3 = |y | { 3i + y }; // infers `y: int`, return type `int`.
1788+
1789+ fun(10); // Prints 10
1790+ closure(20); // Prints 20
1791+ closure(add_3(30)); // Prints 33
17521792
1793+ fun("String"); // Error: mismatched types
1794+
1795+ // Error: mismatched types
1796+ // inference already assigned `closure` the type `|int| -> ()`
1797+ closure("String");
17531798~~~~
1754- let square = |x: int| -> uint { (x * x) as uint };
1799+
1800+ In cases where the compiler needs assistance, the arguments and return
1801+ types may be annotated on closures, using the same notation as shown
1802+ earlier. In the example below, since different types provide an
1803+ implementation for the operator `*`, the argument type for the `x`
1804+ parameter must be explicitly provided.
1805+
1806+ ~~~~{.ignore}
1807+ // Error: the type of `x` must be known to be used with `x * x`
1808+ let square = |x | -> uint { (x * x) as uint };
1809+ ~~~~
1810+
1811+ In the corrected version, the argument type is explicitly annotated,
1812+ while the return type can still be inferred.
1813+
1814+ ~~~~
1815+ let square_explicit = |x: int| -> uint { (x * x) as uint };
1816+ let square_infer = |x: int| { (x * x) as uint };
1817+
1818+ println!("{}", square_explicit(20)); // 400
1819+ println!("{}", square_infer(-20)); // 400
17551820~~~~
17561821
17571822There are several forms of closure, each with its own role. The most
0 commit comments