简体   繁体   English

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

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

In the code below, I explicitly force the name from the main function to be moved into the closure, and everything works just fine: 在下面的代码中,我明确地强制将main函数中的name移到闭包中,并且一切正常:

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

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

    welcome();
}

I would have thought that adding a move to the beginning of the closure would accomplish the same thing, and result in the value being moved and the creation of a FnOnce : 我本以为在闭包的开头添加一个move会完成同样的事情,并导致值被移动并创建FnOnce

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

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

    welcome();
}

Instead, however, I get the error message: 但是,相反,我收到错误消息:

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";
  |         ^^^^

What's the correct way to think about move on a closure in this case? 什么是思考的正确方法move在这种情况下,封闭?

I would have thought that adding a move to the beginning of the closure would accomplish the same thing, … 我本以为在结束处添加一个move会完成相同的事情,……

It kind of does the same thing. 它做同样的事情。 You just forgot to declare name and welcome as mutable. 您只是忘了宣布namewelcome视为可变的。 This code works fine: 这段代码可以正常工作:

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

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

    welcome();
}

Both versions of the closure result in name being moved into the closure. 闭包的两个版本都将name移入闭包。 In the first version, this is implicitly caused by consuming name inside the closure. 在第一个版本中,这是由于使用闭包内部的name而导致的。 The second version does not consume name , but uses the move keyword to force the move. 第二个版本不使用name ,而是使用move关键字强制移动。

… and result in the value being moved and the creation of a FnOnce . …并导致值被移动并创建FnOnce

Moving a value into a closure does not make it FnOnce . 将值移到闭包中不会使其FnOnce If a closure consumes a captured value, it becomes FnOnce , since it obviously can do this only once. 如果关闭消耗捕捉值,就FnOnce ,因为它显然可以做到这一点只有一次。 Thus, the first version of the closure is FnOnce , since it consumes name . 因此,闭包的第一个版本是FnOnce ,因为它使用了name The clousre above is FnMut , and can be called multiple times. 上面的Clousre是FnMut ,可以多次调用。 Calling it twice results in the output 两次调用将导致输出

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

(I used the function trait names somewhat sloppily above. In fact, every closure implements FnOnce , since every closure can be called at least once. Some closures can be called multiple times, so they are FnMut in addition. And some closures that can be called multiple times don't alter their captured state, so they are Fn in addition to the other two traits.) (我在上面FnOnce使用了函数特征名称。实际上, 每个闭包都实现了FnOnce ,因为每个闭包至少可以调用一次。某些闭包可以多次调用,因此它们又是FnMut 。还有一些闭包可以被多次调用不会改变其捕获状态,因此除其他两个特征外,它们均为Fn 。)

暂无
暂无

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

相关问题 为什么在将变量移动到 scope 后 Rust 编译器错误“不能作为不可变借用,因为它也作为可变借用”? - Why does the Rust compiler error with "cannot borrow as immutable because it is also borrowed as mutable" after moving the variable into a scope? 将闭包移动到线程中时,“不能借用可变内容作为可变内容” - “Cannot borrow immutable content as mutable” when moving a closure into a thread 不能将 X 作为不可变借用,因为它在可变闭包中也作为可变借用 - Cannot borrow X as immutable because it is also borrowed as mutable in a mutable closure 无法重新借用变量,因为我无法将不可变局部变量借用为可变 - Unable to re-borrow a variable because I cannot borrow immutable local variable as mutable 在调用一个借用为不可变的闭包时,不能在循环中借用可变的东西吗? - Cannot borrow as mutable in a loop when calling a closure that borrows as immutable? 当范围内仍然有不可变的借用字符串切片引用时,为什么编译器在此可变借用上没有出错? - Why did compiler not error on this mutable borrow when there is an immutable borrowed string slice reference still in scope? 当对象上的特征没有时,为什么引用上的特征会引发“不能借用为可变的,因为它也被借用为不可变的”? - Why does a trait on a reference raise "cannot borrow as mutable because it is also borrowed as immutable" when a trait on an object does not? 为什么从TcpStream更改为特征会导致“无法借用不可变的借用内容可变”? - Why does changing from a TcpStream to a trait cause “cannot borrow immutable borrowed content as mutable”? 错误:不能借用......作为不可变的,因为它也被借为可变的 - error: cannot borrow … as immutable because it is also borrowed as mutable 不能将 x 作为可变借用,因为它也作为不可变错误借用 - cannot borrow x as mutable because it is also borrowed as immutable error
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM