let array = [40];
let mut var = 60;
for element in array.iter().filter(|&x| {*x < var}) {
var += 1; // Error
}
var += 1; // Fine again
对我来说,这段代码似乎完全合法,因为在我实际访问var
之外时,闭包应该结束。
error[E0506]: cannot assign to `var` because it is borrowed
--> src/main.rs:6:9
|
5 | for element in array.iter().filter(|&x| {*x < var}) {
| ---- borrow of `var` occurs here
6 | var += 1; // Error
| ^^^^^^^^ assignment to borrowed `var` occurs here
为什么var
在调用var += 1
时仍然借用,即使闭包的范围已经结束了?到达var += 1
需要结果。虽然可以在没有filter
的情况下执行此类操作,但这会导致我的代码不那么清晰,所以我希望继续使用它。
答案 0 :(得分:4)
关闭应该在我实际访问时结束
没有。 Iterators are lazy。这意味着这里的操作顺序是:
next
。next
。重复此步骤,直到条件通过。您正在过滤器关闭内捕获val
。您还尝试在循环中修改它。这意味着必须同时存在可变引用和不可变引用,这是不允许的。
您可以使用Cell
进行内部可变性:
use std::cell::Cell;
fn main() {
let array = [40];
let var = Cell::new(60);
for element in array.iter().filter(|&&x| x < var.get()) {
var.set(var.get() + 1);
}
let mut var = var.get();
var += 1;
}
答案 1 :(得分:2)
Shepmaster的答案是正确的(我不知道迭代器是 懒惰的),但是如果你不想要var
检查(即在循环期间要更改的filter
条件),您可以使用move
closure:
filter(move |&x| *x < var)
由于i32
实现了Copy
,因此只会为了关闭而复制var
的值。