我试图通过使用小帮手闭包来让我的代码的某些部分更容易阅读。
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"这样做的方式?
答案 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
为你照顾它。