Closures
Closures or lambda expressions have types which cannot be named. However, they
implement special Fn,
FnMut, and
FnOnce traits:
fn apply_with_log(func: impl FnOnce(i32) -> i32, input: i32) -> i32 { println!("Calling function on {input}"); func(input) } fn main() { let add_3 = |x| x + 3; let mul_5 = |x| x * 5; println!("add_3: {}", apply_with_log(add_3, 10)); println!("mul_5: {}", apply_with_log(mul_5, 20)); }
If you have an FnOnce, you may only call it once. It might consume captured values.
An FnMut might mutate captured values, so you can call it multiple times but not concurrently.
An Fn neither consumes nor mutates captured values, or perhaps captures nothing at all, so it can
be called multiple times concurrently.
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.
move closures only implement FnOnce.