iterator - 在迭代另一个属性时修改结构的一个属性

标签 iterator rust borrow-checker

我有一个包含 2 个 Vec 的结构。我希望能够在修改另一个的同时迭代一个。这是一个示例程序:

use std::slice;

struct S {
    a: Vec<i32>,
    b: Vec<i32>
}

impl S {
    fn a_iter<'a>(&'a self) -> slice::Iter<i32>  {
        self.a.iter()
    }
    fn a_push(&mut self, val: i32) {
        self.a.push(val);
    }
    fn b_push(&mut self, val: i32) {
        self.b.push(val);
    }
}

fn main() {
    let mut s = S { a: Vec::new(), b: Vec::new() };
    s.a_push(1);
    s.a_push(2);
    s.a_push(3);

    for a_val in s.a_iter() {
        s.b_push(a_val*2);
    }
}

但是有这个编译错误:

$ rustc iterexample.rs 
iterexample.rs:28:9: 28:10 error: cannot borrow `s` as mutable because it is also borrowed as immutable
iterexample.rs:28         s.b_push(a_val*2);
                           ^
note: in expansion of for loop expansion
 iterexample.rs:26:5: 29:6 note: expansion site
iterexample.rs:26:18: 26:19 note: previous borrow of `s` occurs here; the immutable borrow prevents subsequent moves or mutable borrows of `s` until the borrow ends
iterexample.rs:26     for a_val in s.a_iter() {
                                   ^
note: in expansion of for loop expansion
iterexample.rs:26:5: 29:6 note: expansion site
iterexample.rs:29:6: 29:6 note: previous borrow ends here
iterexample.rs:26     for a_val in s.a_iter() {
iterexample.rs:27         println!("Looking at {}", a_val);
iterexample.rs:28         s.b_push(a_val*2);
iterexample.rs:29     }
                      ^
note: in expansion of for loop expansion
iterexample.rs:26:5: 29:6 note: expansion site
error: aborting due to previous error

我明白编译器在提示什么。我在 for 循环中借用了 self,因为我还在循环它。

从概念上讲,应该有一种方法可以做到这一点。我只修改 s.b,而不是修改我正在循环的东西 (s.a)。有没有办法编写我的程序来演示这种分离,并允许这种程序编译?

这是一个较大程序的简化示例,因此我需要保持一般结构相同(一个包含一些东西的结构,其中一个将被迭代,另一个将被更新)。

最佳答案

如果使用 s.a.it 而不是 s.a_iter(),则可以消除错误。 您当前的解决方案不起作用,因为从 s.a_iter() 返回的迭代器保留了 s 的引用,它具有与 s 相同的生命周期本身,因此在该引用存在之前,您不能借用 s 中的可变内容。发生这种情况的具体原因是:

the compiler stops at the function call boundary when evaluating generic parameters

(你的生命周期)

这里有一个很好的答案,其中包含对一个非常相似的问题的完整解释: cannot borrow `self.x` as immutable because `*self` is also borrowed as mutable

编辑

一个可能的解决方案是将操作放在 S 中,而不是从 S 中取出迭代器。您可以在 S 中定义这样的方法:

fn foreach_in_a_push_to_b<F>(&mut self, func: F) where F : Fn(&i32) -> i32 {
    for a_val in self.a.iter() {
        self.b.push(func(a_val));
    }
}

然后

s.foreach_in_a_push_to_b(|&x| x * 2);

关于iterator - 在迭代另一个属性时修改结构的一个属性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31193408/

相关文章:

c++ - reverse_iterator 适配器

java - 流式传输并从自定义类获取并打印出值

rust - 为什么在改变Result的类型时,匹配一个Result需要显式的Err?

rust - 为什么不能在同一结构中存储值和对该值的引用?

reference - 尝试转移所有权时无法移出借用的内容

rust - 为什么在尝试获取对装箱值的引用时得到预期类型 `()`?

python - 生成器字典内的迭代变量

scala - 如何在 Scala 中返回迭代器?

file-io - 打开文件返回ErrorKind::Other 'Error: Os, code: 20, message: “Not a directory”'

rust - 返回迭代器(或任何其他特征)的正确方法是什么?