2017-07-04 47 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