Closures
Multiple lines:
Single line:
Closures in variables do not need type specification, because they are private to functions and are not exposes outside. Instead, we allow the compiler to infer all that information. However, we can add types if we want to.
Caching Results
Sometimes it might be useful to define a closure that calculates some result that
we want to reuse multiple times. We use structs for that.
It’s analogical to Lazy<T>
of .NET C#.
When we ask for a value()
, the first time we do it, closure will be executed.
Consecutive value()
calls will return a cached value of the closure’s result.
When defining closure as a field of a struct, we need to specify its type. In
the case above, the type is Fn(u32) -> u32
.
Capturing Environment
Closures can capture variables defined outside of the closure:
Functions cannot do that. Captures can be done in three ways, depending on the
Fn...
trait being used:
FnOnce
- Instances ofFnOnce
can be called, but might not be callable multiple times. Because of this, if the only thing known about a type is that it implementsFnOnce
, it can only be called once, because it takes ownership of passed arguments.FnMut
- it mutably borrows external values. Sutrait ofFnOnce
.Fn
- it immutably borrows external values. Sutrait ofFnOnce
.
Function Pointers
Functions can also be passed in place of closures. Function pointers implement
all three closure traits: FnOnce
, FnMut
, Fn
.