As the title states I am looking to return a closure from a function which has some initial, mutable state. In the following examples CowRow
is a struct
with a time
field. It also has a String
field, so is thus not copyable. Concretely, I would like a function that looks something like:
pub fn agg1() -> Box<Fn(&CowRow)> {
let res = 0;
Box::new(move |r| { res += r.time; })
}
Of course, this produces the error:
src/queries.rs:9:25: 9:38 error: cannot assign to captured outer variable in an `Fn` closure
src/queries.rs:9 Box::new(move |r| { res += r.time; })
^~~~~~~~~~~~~
src/queries.rs:9:14: 9:41 help: consider changing this closure to take self by mutable reference
src/queries.rs:9 Box::new(move |r| { res += r.time; })
^~~~~~~~
It is my understanding that Rust needs to know about the size of returned values and because closures borrow their stack frame from their environment we need to introduce the Box
and move
to get a size for the return and put the closure on the heap.
Is there some way to also put res
on the heap in this closures environment? Or otherwise allow for this behaviour? Of course I have looked at: Cannot borrow captured outer variable in an `Fn` closure as mutable but this seems overly complicated and it's not clear to me how this would perform in the case of multiple threads running this function simultaneously.
Another technique I tried was to change the closure to take a mutable reference to an i32
which I can initialise outside of the agg
function. Example:
pub fn agg0() -> Box<Fn(&CowRow, &mut i32)> {
Box::new(move |r, &mut acc| { acc += r.time; })
}
However, this produces the error:
src/queries.rs:4:35: 4:48 error: re-assignment of immutable variable `acc` [E0384]
src/queries.rs:4 Box::new(move |r, &mut acc| { acc += r.time; })
^~~~~~~~~~~~~
src/queries.rs:4:35: 4:48 help: run `rustc --explain E0384` to see a detailed explanation
src/queries.rs:4:28: 4:31 note: prior assignment occurs here
src/queries.rs:4 Box::new(move |r, &mut acc| { acc += r.time; })
This one is a total mystery to me.