Type anonymity
Closures succinctly capture variables from enclosing scopes. Does this have any consequences? It surely does. Observe how using a closure as a function parameter requires generics, which is necessary because of how they are defined:
1. // `F` must be generic.
2. fn apply<F>(f: F) where
3. F: FnOnce() {
4. f();
5. }
When a closure is defined, the compiler implicitly creates a new
anonymous structure to store the captured variables inside, meanwhile
implementing the functionality via one of the traits: Fn, FnMut, or
FnOnce for this unknown type. This type is assigned to the variable which
is stored until calling.
Since this new type is of unknown type, any usage in a function will require
generics. However, an unbounded type parameter <T> would still be ambiguous
and not be allowed. Thus, bounding by one of the traits: Fn, FnMut, or
FnOnce (which it implements) is sufficient to specify its type.
1. // `F` must implement `Fn` for a closure which takes no
2. // inputs and returns nothing - exactly what is required
3. // for `print`.
4. fn apply<F>(f: F) where
5. F: Fn() {
6. f();
7. }
9. fn main() {
10. let x = 7;
12. // Capture `x` into an anonymous type and implement
13. // `Fn` for it. Store it in `print`.
14. let print = || println!("{}", x);
16. apply(print);
17. }
See also:
A thorough analysis, Fn, FnMut,
and FnOnce
