无法分配给闭包中使用的变量,因为它是借用的

时间:2017-08-10 21:42:58

标签: rust closures

我试图通过使用小帮手闭包来让我的代码的某些部分更容易阅读。

fn main() {
    let mut loop_index = 0;

    let get_src_index = || return loop_index % 2;
    let get_dst_index = || return (loop_index + 1) % 2;

    loop_index += 1;
}

还有一些使用get_src_index()get_dst_index()的闭包,但它们对问题并不重要。问题是我无法再修改loop_index

error[E0506]: cannot assign to `loop_index` because it is borrowed
 --> src/main.rs:6:5
  |
4 |     let get_src_index = || return loop_index % 2;
  |                         -- borrow of `loop_index` occurs here
5 |     let get_dst_index = || return (loop_index + 1) % 2;
6 |     loop_index += 1;
  |     ^^^^^^^^^^^^^^^ assignment to borrowed `loop_index` occurs here

我不太明白为什么Rust不允许递增loop_index变量。还有更多" Rusty"这样做的方式?

1 个答案:

答案 0 :(得分:4)

正如错误消息所示,您无法更改该值,因为它是借用的。就像你说过的那样:

let mut loop_index = 0;
let foo = &loop_index;
loop_index += 1;

您不能modify a value while there is an outstanding immutable borrow。这是Rust的一个基本概念,它支撑着它提供的安全性。

为什么闭包有引用变量?这就是闭包的整点 - capture the environment。闭包推断如何根据内部发生的操作捕获变量,在这种情况下,引用就足够了。

这通常是您想要的,因为参考很容易传递。在 this 的情况下,您有数字,所以没有理由更喜欢该引用。我们可以使用move关键字将数字移动到闭包中。由于数字实现了Copy,因此这将进行复制。然后,闭包与现有值完全分开:

let mut loop_index = 0;

let get_src_index = move || loop_index % 2; // No need for `return`
let get_dst_index = move || (loop_index + 1) % 2;

loop_index += 1;

但是,我不认为这些特殊的关闭确实会给你带来什么。整数运算通常很便宜,条件通常不那么便宜,所以做额外的计算可能会更好。

如果您需要能够修改loop_index并将更改反映在闭包内,则可以使用Cell

use std::cell::Cell;

fn main() {
    let mut loop_index = Cell::new(0);

    let get_src_index = || loop_index.get() % 2;
    let get_dst_index = || (loop_index.get() + 1) % 2;

    loop_index.set(loop_index.get() + 1);
}

即使更好,在许多情况下,无论如何都不需要维护自己的循环索引。 Iterator::enumerate为你照顾它。

相关问题