繁体   English   中英

为什么将值移到闭包中仍然会出现错误消息“无法借用不可变的局部变量作为可变变量”?

[英]Why does moving a value into a closure still have the error message “cannot borrow immutable local variable as mutable”?

在下面的代码中,我明确地强制将main函数中的name移到闭包中,并且一切正常:

fn main() {
    let name = String::from("Alice");

    let welcome = || {
        let mut name = name;
        name += " and Bob";
        println!("Welcome, {}", name);
    };

    welcome();
}

我本以为在闭包的开头添加一个move会完成同样的事情,并导致值被移动并创建FnOnce

fn main() {
    let name = String::from("Alice");

    let welcome = move || {
        name += " and Bob";
        println!("Welcome, {}", name);
    };

    welcome();
}

但是,相反,我收到错误消息:

error[E0596]: cannot borrow immutable local variable `welcome` as mutable
 --> main.rs:9:5
  |
4 |     let welcome = move || {
  |         ------- help: make this binding mutable: `mut welcome`
...
9 |     welcome();
  |     ^^^^^^^ cannot borrow mutably

error[E0596]: cannot borrow captured outer variable in an `FnMut` closure as mutable
 --> main.rs:5:9
  |
5 |         name += " and Bob";
  |         ^^^^

什么是思考的正确方法move在这种情况下,封闭?

我本以为在结束处添加一个move会完成相同的事情,……

它做同样的事情。 您只是忘了宣布namewelcome视为可变的。 这段代码可以正常工作:

fn main() {
    let mut name = String::from("Alice");

    let mut welcome = move || {
        name += " and Bob";
        println!("Welcome, {}", name);
    };

    welcome();
}

闭包的两个版本都将name移入闭包。 在第一个版本中,这是由于使用闭包内部的name而导致的。 第二个版本不使用name ,而是使用move关键字强制移动。

…并导致值被移动并创建FnOnce

将值移到闭包中不会使其FnOnce 如果关闭消耗捕捉值,就FnOnce ,因为它显然可以做到这一点只有一次。 因此,闭包的第一个版本是FnOnce ,因为它使用了name 上面的Clousre是FnMut ,可以多次调用。 两次调用将导致输出

Welcome, Alice and Bob
Welcome, Alice and Bob and Bob

(我在上面FnOnce使用了函数特征名称。实际上, 每个闭包都实现了FnOnce ,因为每个闭包至少可以调用一次。某些闭包可以多次调用,因此它们又是FnMut 。还有一些闭包可以被多次调用不会改变其捕获状态,因此除其他两个特征外,它们均为Fn 。)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM