在下面的代码中,我明确地强制将 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
的正确方法是什么?
最佳答案
I would have thought that adding a
move
to the beginning of the closure would accomplish the same thing, …
它有点做同样的事情。您只是忘记将 name
和 welcome
声明为可变的。此代码工作正常:
fn main() {
let mut name = String::from("Alice");
let mut welcome = move || {
name += " and Bob";
println!("Welcome, {}", name);
};
welcome();
}
两个版本的闭包都会导致 name
被移动到闭包中。在第一个版本中,这是由在闭包内使用 name
隐式引起的。第二个版本不使用 name
,而是使用 move
关键字强制移动。
… and result in the value being moved and the creation of a
FnOnce
.
将值移动到闭包中不会使其成为 FnOnce
。如果一个闭包消费一个捕获的值,它就变成了FnOnce
,因为它显然只能这样做一次。因此,闭包的第一个版本是 FnOnce
,因为它使用 name
。上面的clousre是FnMut
,可以多次调用。调用它两次导致输出
Welcome, Alice and Bob
Welcome, Alice and Bob and Bob
(我在上面草率地使用了函数特征名称。事实上,每个 闭包都实现了 FnOnce
,因为每个闭包至少可以被调用一次。有些闭包可以多次调用,所以它们是FnMut
。而一些可以多次调用的闭包不会改变它们的捕获状态,所以它们是 Fn
除了其他两个特征。)
关于rust - 为什么将值移动到闭包中仍然有错误消息 "cannot borrow immutable local variable as mutable"?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53029622/