无法移出 Fn 闭包中捕获的外部变量 [英] Cannot move out of captured outer variable in an Fn closure

查看:55
本文介绍了无法移出 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,一个不可变的引用关闭):

A closure which implements Fn can be called multiple times (the receiver parameter is &self, an immutable reference to the closure):

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() ->字符串,你可以这样做:

This means that with your closure Fn() -> String, you could do this:

let s1 = adder();
let s2 = adder();

现在您将拥有两个 String ,尽管您只从一个开始!魔术?您当然可以通过克隆原始字符串来获得另一个字符串,但我们在这里不这样做.所以它显然行不通.

Now you would have two Strings although you only started with one! Magic? You can of course get another string by cloning the original string, but we don't do that here. So it clearly can't work.

您可以通过两种方式解决此问题.要么你不需要多次调用你的闭包.在这种情况下,您可以简单地将 Fn 更改为 FnOnce(要求不高的特性).FnOnce 闭包只能被调用......好吧......一次.这有效:

You can fix that in two ways. Either you don't need your closure to be called multiple times. In that case you can simply change Fn to FnOnce (a less demanding trait). An FnOnce closure can only be called ... well ... once. This works:

fn make_adder(x: String) -> Box<FnOnce() -> String> {
    Box::new(|| x)
}

另一方面,也许你希望闭包被多次调用,并且总是希望返回一个新的字符串克隆.你可以这样做:

On the other hand, maybe you want the closure to be called multiple times and always want to return a new clone of the string. You can do that like this:

fn make_adder(x: String) -> Box<Fn() -> String> {
    Box::new(move || x.clone())
}

这里我们添加了一个 .clone() 调用(因为在 Rust 中,深度克隆永远不会是隐式的!)并且我们添加了 move 关键字.后者对于将字符串 x 显式移动到闭包中是必要的,而不仅仅是借用它.

Here we added a .clone() call (since in Rust, deep clones are never implicit!) and we added the move keyword. The latter is necessary to explicitly move the string x into the closure, not just borrow it.

这篇关于无法移出 Fn 闭包中捕获的外部变量的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆