Rust 0.12.
Let's say I have a sendable closure, that is defined entirely separately from the code that should spawn it in another task.
Closure type:
type closure_type = ||: 'static + Send;
Code:
let do_stuff : closure_type = || println!("stuff"); // "uknown" procedure
let outer_fun = || {
spawn(proc() {
do_stuff();
});
};
outer_fun(); // someone else calls this
The above example fails to compile with a message "can not move out of captured outer variable" at the "proc()" scope. Why does the outer_fun
captures do_stuff
variable if it is not used there?
After tinkering a bit, I found that one possible solution would be to explicitly pass do_stuff
function to outer_fun
closure (this compiles):
let do_stuff : closure_type = || println!("stuff");
let outer_fun = | do_do_stuff: closure_type | {
spawn(proc() {
do_do_stuff();
});
};
outer_fun(do_stuff); // I don't want someone else to know about "do_stuff"!
But this closes the possibility of someone else invoking the spawn without knowing what it spawns.
Obviously, my brain might be a bit damaged by unconstrained consumption of Javascript, so I must humbly ask: what would be a correct way to accomplish something like this in Rust?
UPDATE: Just spawn a proc on the main callback! Duh.
let do_stuff = || spawn(proc() println!("Hello"));
let do_spawn = || {
do_stuff();
};
for i in range(1u, 10) {
do_spawn(); // Even multiple times.
}
Why does the
outer_fun
capturesdo_stuff
variable if it is not used there?
But it is used there! do_stuff
appears inside closure body, and closures are lexical, so do_stuff
is necessarily captured by outer_fun
.
Currently closures capture every variable by reference. This is useful because it allows you to mutate "outer" variables as if the closure body were embedded directly in the outer code. However, this does preclude you from moving out of captured variables (because it would mean moving out of a reference).
proc()
s, on the other hand, have their environment on the heap, and they are callable only once. It means that they move every captured value into their environment. However, you're trying to use do_stuff
(which was captured by the outer_fun
closure) inside proc()
body, which is captured by reference and cannot be moved into proc()
, so here is your error.
I don't think it is possible to do what you want to yet. Currently there is an accepted unboxed closures proposal. Proper unboxed closures will soon be implemented; in particular unboxed closures can capture their environment by value, just like proc()
s (which will be superseded by explicitly boxed unboxed closures [no pun intended]). When unboxed closures land, as far as I understand, you'll be able to compile your first example exactly as it is (only changing proc()
to box ||
or something).