生锈 – 无法移出Fn闭包中捕获的外部变量

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移动到闭包中所必需的,而不仅仅是借用它.

点赞