2017-08-10 43 views
0

我想通过使用小型帮助程序闭包来使代码的某些部分更易于阅读。因为借用而无法分配给闭包中使用的变量

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 

我不明白为什么锈不允许递增loop_index变量。有没有更“生锈”的方式来做到这一点?

+1

编译器的消息似乎不符合上面的代码。请制作一个MCVE,最好带一个链接到[Rust Playground](https://play.rust-lang.org/)。 –

+0

@ E_net4也吸引了我。 OP将代码拆分成两个块,但它是两个组合出现错误。 – Shepmaster

回答

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。 Closure 推断如何根据内部发生的操作捕获变量,在这种情况下,参考就足够了。

这通常是你想要的,因为参考很容易传递。在这个的情况下,你有数字,所以没有理由偏好参考。我们可以使用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照顾你。

+0

谢谢你的解释。我不认为我可以在这里使用'enumerate()',但使用'Cell'完美无瑕! :) –

相关问题