What actually is a closure?
A closure is just an anonymous struct containing the captured values in three ways: borrowing immutably(Fn
), borrowing mutably(FnMut
), and taking ownership(FnOnce
). The closure will decide which of these to use based on what the body of the function does with the captured values.
FnOnce
, applies to closures that can be called once. A closure that moves captured values out of its body will only implementFnOnce
and none of the otherFn
traits, because it can only be called once.FnMut
, applies to closures that don't move captured values out of their body, but that might mutate the captured values.Fn
, applies to closures that don't move captured values out of their body and that don't mutate captured values, as well as closures that capture nothing from their environment.
The following code with a closure
let mut count: usize = 0;
let mut counter = || { count += 1; count };
assert_eq!(counter(), 1);
assert_eq!(counter(), 2);
assert_eq!(counter(), 3);
is roughly equivalent to the following code with a struct.
struct Counter {
count: usize
}
impl std::ops::FnMut<()> for Counter {
type Output = usize;
fn call_mut(&mut self, args: ()) -> Self::Output {
self.count += 1;
self.count
}
}
let mut counter = Counter { 0 };
assert_eq!(counter(), 1);
assert_eq!(counter(), 2);
assert_eq!(counter(), 3)
Full working code: https://play.rust-lang.org/?version=nightly&mode=debug&edition=2018&gist=07ce9e7625cccaf04fc69d668e2a3203
Reference