Does it create a new thread and then execute that anonymous function inside the new thread?
I noticed many ownership / borrowing restrictions when I'm working with a closure. For example, if I have Fn()
, I cannot pass a mutable variable inside the closure or it needs to be wrapped with a Mutex
:
fn helloworld(f: &Fn(f64)) {
f(42f64);
}
pub fn main() {
let mut killer = 2;
helloworld(&|n| {
println!("{}", n);
killer += 1;
});
}
If a closure can be unsafe like that then something asynchronous or parallel is going on behind the scene and that's why Rust compiler doesn't let me to compile such code.
I might just be confused because I'm coming from a JavaScript / Python world and things are completely different there.
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:
is de-sugared into something similar to:
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
andFnOnce
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 useFnOnce
(although not as a trait object like you're doing in your example).