Closures
Closures or lambda expressions have types which cannot be named. However, they
implement special Fn
,
FnMut
, and
FnOnce
traits:
The special type fn
refers to function pointers - either the address of a
function, or a closure that captures nothing.
Speaker Notes
This slide should take about 10 minutes.
An Fn
(e.g. add_suffix
) neither consumes nor mutates captured values. It can
be called needing only a shared reference to the closure, which means the
closure can be executed repeatedly and even concurrently.
An FnMut
(e.g. accumulate
) might mutate captured values. The closure object
is accessed via exclusive reference, so it can be called repeatedly but not
concurrently.
If you have an FnOnce
(e.g. take_and_reverse
), you may only call it once.
Doing so consumes the closure and any values captured by move.
FnMut
is a subtype of FnOnce
. Fn
is a subtype of FnMut
and FnOnce
.
I.e. you can use an FnMut
wherever an FnOnce
is called for, and you can use
an Fn
wherever an FnMut
or FnOnce
is called for.
When you define a function that takes a closure, you should take FnOnce
if you
can (i.e. you call it once), or FnMut
else, and last Fn
. This allows the
most flexibility for the caller.
In contrast, when you have a closure, the most flexible you can have is Fn
(which can be passed to a consumer of any of the 3 closure traits), then
FnMut
, and lastly FnOnce
.
The compiler also infers Copy
(e.g. for add_suffix
) and Clone
(e.g.
take_and_reverse
), depending on what the closure captures. Function pointers
(references to fn
items) implement Copy
and Fn
.