2017-07-04 36 views
3

我想根據Iterator::next中當前枚舉變體的某些屬性更改枚舉變量。我有兩個嘗試,均未編譯:如果我不與選擇的參考工作當選擇器是可變參考時在匹配中更改選擇器

enum Test { 
    A(Vec<usize>), 
    B, 
} 

impl<'a> Iterator for Test { 
    type Item = usize; 

    fn next(&mut self) -> Option<Self::Item> { 
     // attempt 1 
     if let Test::A(ref a) = *self { 
      if a.len() == 0 { 
       *self = Test::B; // doesn't work because a is borrowed 
      }; 
     } 

     // attempt 2 
     *self = match *self { 
      Test::A(ref a) if a.len() == 0 => Test::B, 
      _ => *self, // cannot move out of borrowed context 
     }; 
     None 
    } 
} 

fn main() {} 

我的第二次嘗試不工作:

let mut a = Test::A(vec![]); 
a = match a { 
    Test::A(ref a) if a.len() == 0 => Test::B, 
    _ => a, 
}; 

這個問題是關係到Is there a way to use match() in rust when modifying the selector?,但解決方案建議沒有泛型:只有在兩個分支中執行相同的函數時纔有效。

什麼是Rustacean的方式來實現我的目標?

回答

3

由於一個if let/match塊內把在條件不是很可讀,我只想用一個輔助函數來測試它:

impl Test { 
    fn is_empty_a(&self) -> bool { 
     if let Test::A(ref a) = *self { 
      a.len() == 0 
     } else { 
      false 
     } 
    } 
} 

然後不應該有任何問題,借款:

impl<'a> Iterator for Test { 
    type Item = usize; 

    fn next(&mut self) -> Option<Self::Item> { 
     if self.is_empty_a() { 
      *self = Test::B; 
     } 
     None 
    } 
} 
+0

謝謝!出於好奇:有沒有辦法在不使用函數的情況下避免借用問題? –

+0

我不這麼認爲,除非你正在處理複製對象(或者你先克隆它們); 「如果讓」和「匹配」都借用了它們之後的值,所以你不能在它們的塊中自由使用它。 – ljedrz