2017-07-04 2 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?に関連しているが、解決策私は2つのコンパイルどちらも試みを、持っていますジェネリックではないことが提案されています:同じ機能が両方のブランチで実行される場合にのみ機能します。

私の目標を達成するためにルーセアの方法は何ですか?

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

をし、任意の借入の問題があってはならない:if let/matchブロックの内側に置いたときの条件は非常に読みやすいではありませんので

答えて

3

、私はちょうどそれをテストするためにヘルパー関数を使用します。

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

あなたが 'Copy'可能なオブジェクトを扱っていない限り(あるいは' clone() 'を最初に扱っていない限り)、そうは思わないでしょう。 'let 'と' match'の両方がそれらの後ろに来るので、ブロック内で自由に使うことはできません。 – ljedrz

関連する問題