There are two layers to this question.
First, a closure in Rust is just an anonymously-defined type that implements one or more "callable" traits. For example, this:
fn main() {
let a = 6;
let closure = |b| {
println!("product is: {}", a * b);
};
closure(7);
}
is de-sugared into something similar to:
fn main() {
let a = 6;
let closure = {
struct Closure<'a> {
a: &'a i32,
}
impl<'a> Fn<(i32,)> for Closure<'a> {
extern "rust-call" fn call(&self, (b,): (i32,)) {
println!("product is: {}", (*self.a) * b);
}
}
impl<'a> FnMut<(i32,)> for Closure<'a> {
extern "rust-call" fn call_mut(&mut self, args: (i32,)) {
self.call(args)
}
}
impl<'a> FnOnce<(i32,)> for Closure<'a> {
type Output = ();
extern "rust-call" fn call_once(self, args: (i32,)) {
self.call(args)
}
}
Closure {
a: &a,
}
};
FnOnce::call_once(closure, (7,));
}
Note: the above code relies on unstable, internal details and will not work on a stable compiler. It is provided for explanation only; you should not use this pattern yourself.
There's no threading involved, and nothing magical is happening. They boil down to a regular function call with an extra initial "context" argument.
This brings us to the second layer, which is why your specific code doesn't work: because you told the compiler to forbid it. One critical concern for callables is how the context is passed to the callable's code. This is represented by the Fn
, FnMut
and FnOnce
traits (which are explained in the answer to the question When does a closure implement Fn, FnMut and FnOnce?). By taking &Fn(f64)
, you've restricted yourself to only accepting closures which require immutable access to their context.
If you want a closure to be able to mutate its context, you need to use FnMut
instead. Or, if you only need to call a closure once, you can use FnOnce
(although not as a trait object like you're doing in your example).
Fn()
, I cannot pass a mutable variable inside the closure or it needs to be wrapped with aMutex
"? – BoiethiosFnMut
: play.rust-lang.org/… But I let someone with more knowledge to answer with detailed explanations. – Boiethios