如何在相同元素上迭代另一个可变迭代中的可变元素?

时间:2017-09-01 15:09:32

标签: rust borrow-checker

我有一个Element的数组,我想迭代它来做一些事情,然后迭代循环中的所有Element来做某事。元素之间存在关系,所以我想迭代到所有其他元素来检查一些东西。这些元素是可变引用的原因。它有点宽泛,但我试图做到一般(也许我不应该)。

struct Element;

impl Element {
    fn doSomething(&self, e: &Element) {}
}

fn main() {
    let mut elements = [Element, Element, Element, Element];

    for e in &mut elements {

        // Do stuff...

        for f in &mut elements {
            e.doSomething(f);
        }
    }
}

正如预期的那样,我收到了这个错误:

  

不能一次多次将elements借用为可变

我知道a normal behavior in Rust,但推荐的避免此错误的方法是什么?我应该先复制这些元素吗?忘记循环并以不同的方式迭代?了解代码设计?

有生锈的方式吗?

免责声明:我知道这是一个常见的错误,可能会在别处回答,但我又一次失败了。我没有找到相关的答案,也许我不知道如何搜索。对不起,如果它是重复的。

2 个答案:

答案 0 :(得分:5)

您可以使用索引迭代而不是使用迭代器进行迭代。然后,在内部循环内部,您可以使用split_at_mut在同一切片中获取两个可变引用。

for i in 0..elements.len() {
    for j in 0..elements.len() {
        let (e, f) = if i < j {
            // `i` is in the left half
            let (left, right) = elements.split_at_mut(j);
            (&mut left[i], &mut right[0])
        } else if i == j {
            // cannot obtain two mutable references to the
            // same element
            continue;
        } else {
            // `i` is in the right half
            let (left, right) = elements.split_at_mut(i);
            (&mut right[0], &mut left[j])
        };
        e.doSomething(f);
    }
}

答案 1 :(得分:2)

你不能这样做,期间。 The rules of references州,强调我的:

  

在任何时候,您可以拥有以下两者,但不能同时拥有以下两者:

     
      
  • 一个可变引用。
  •   
  • 任意数量的不可变引用。
  •   

在第一次迭代中,您试图获得两个对数组中第一个元素的可变引用。必须禁止这样做。

您的方法根本不需要可变引用(fn doSomething(&self, e: &Element) {}),所以最简单的方法就是切换到不可变迭代器:

for e in &elements {
    for f in &elements {
        e.doSomething(f);
    }
}

如果您确实需要在循环内执行变异,则还需要切换到interior mutability。这会将规则的执行从编译时间转移到运行时,因此如果您尝试同时获得对同一项目的两个可变引用,您现在会感到恐慌。