2017-09-01 95 views
3

我有一個Element s的數組,我想遍歷它做一些事情,然後遍歷循環內的所有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); 
     } 
    } 
} 

正如預期的那樣,我得到這個錯誤:

cannot borrow elements as mutable more than once at a time

我知道這是a normal behavior in Rust,但什麼是推薦的方式,以避免這個錯誤?我應該先複製這些元素嗎?忘記循環並以不同的方式迭代?瞭解代碼設計?

有沒有一種生鏽的方式來做到這一點?

免責聲明:我知道這是一個常見的錯誤,它可能會在別處得到解答,但我又一次迷失了。我沒有找到相關的答案,也許我不知道如何搜索。對不起,如果它是重複的。

+0

你不能用迭代器來做到這一點。我只是使用基於索引的迭代('for i in 0..elements.len()') –

回答

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

請注意,這個解決方案與OP的代碼略有不同,事實上'doSomething'永遠不會被調用兩個值。另一個答案描述了原因。 – Shepmaster

2

你不能這樣做,期間。 The rules of references狀態,重點煤礦:

At any given time, you can have either but not both of:

  • One mutable reference.
  • Any number of immutable references.

在第一個迭代,你試圖讓到陣列中的第一個元素可變引用。這必須被禁止。

你的方法不需要在所有(fn doSomething(&self, e: &Element) {})可變的引用,所以最簡單的做法就是隻需切換到不可改變的迭代器:

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

如果你真的確實需要在循環內進行突變,你也將需要切換到interior mutability。這將規則的執行從編譯時間轉移到運行時間,所以如果您試圖同時獲取兩個可變引用到同一個項目,您將會感到恐慌。