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:
// `F` must be generic.
fn apply<F>(f: F) where
F: FnOnce() {
f();
}
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
, orFnOnce
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
, orFnOnce
(which it implements) is sufficient to specify its type.
// `F` must implement `Fn` for a closure which takes no
// inputs and returns nothing - exactly what is required
// for `print`.
fn apply<F>(f: F) where
F: Fn() {
f();
}
fn main() {
let x = 7;
// Capture `x` into an anonymous type and implement
// `Fn` for it. Store it in `print`.
let print = || println!("{}", x);
apply(print);
}
See also:
A thorough analysis, Fn
, FnMut
,
and FnOnce