【发布时间】:2016-04-08 23:57:42
【问题描述】:
正如标题所述,我希望从具有一些初始可变状态的函数返回闭包。在以下示例中,CowRow 是带有 time 字段的 struct。它还有一个String 字段,因此不可复制。具体来说,我想要一个看起来像这样的函数:
pub fn agg1() -> Box<Fn(&CowRow)> {
let res = 0;
Box::new(move |r| { res += r.time; })
}
当然,这会产生错误:
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; })
^~~~~~~~
据我了解,Rust 需要知道返回值的大小,并且由于闭包从它们的环境中借用了它们的堆栈框架,我们需要引入 Box 和 move 来获得返回值的大小并将堆上的闭包。
有没有办法在这个闭包环境中也将res 放在堆上?或者以其他方式允许这种行为?当然我看过:Cannot borrow captured outer variable in an `Fn` closure as mutable,但这似乎过于复杂,我不清楚在多个线程同时运行此功能的情况下这将如何执行。
我尝试的另一种技术是更改闭包以获取对i32 的可变引用,我可以在agg 函数之外对其进行初始化。示例:
pub fn agg0() -> Box<Fn(&CowRow, &mut i32)> {
Box::new(move |r, &mut acc| { acc += r.time; })
}
但是,这会产生错误:
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; })
这对我来说完全是个谜。
【问题讨论】: