fn make_adder(x: String) -> Box<Fn() -> String> {
Box::new(|| x)
}
fn main() {
make_adder(String::from("a"));
}
这会导致此错误:
error[E0507]: cannot move out of captured outer variable in an `Fn` closure
--> src/main.rs:2:17
|
1 | fn make_adder(x: String) -> Box<Fn() -> String> {
| - captured outer variable
2 | Box::new(|| x)
| ^ cannot move out of captured outer variable in an `Fn` closure
我怎样才能使它正确?
最佳答案 可以多次调用实现
Fn
的闭包(接收器参数是& self,对闭包的不可变引用):
fn call_multiple_times<F: Fn(u8) -> i32>(f: F) {
// Works! We can call the closure mutliple times
let a = f(1);
let b = f(27);
let c = f(31);
}
这意味着你的闭包Fn() – >字符串,你可以这样做:
let s1 = adder();
let s2 = adder();
现在你有两个字符串虽然你只开始一个!魔法?您当然可以通过克隆原始字符串来获取另一个字符串,但我们不会在此处执行此操作.所以它显然无法奏效.
您可以通过两种方式解决这个问题.要么你不需要多次调用你的闭包.在这种情况下,您可以简单地将Fn更改为FnOnce
(要求较低的特性). FnOnce闭合只能被称为……好吧……一次.这有效:
fn make_adder(x: String) -> Box<FnOnce() -> String> {
Box::new(|| x)
}
另一方面,也许您希望多次调用闭包并始终希望返回字符串的新克隆.你可以这样做:
fn make_adder(x: String) -> Box<Fn() -> String> {
Box::new(move || x.clone())
}
在这里我们添加了一个.clone()调用(因为在Rust中,深度克隆从不隐式!)并且我们添加了move关键字.后者是明确将字符串x移动到闭包中所必需的,而不仅仅是借用它.