[英]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. 您只是忘了宣布
name
而welcome
视为可变的。 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.