当selector是可变引用时,在匹配中更改选择器

时间:2017-07-04 07:48:33

标签: rust

我想根据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实现目标的方法是什么?

1 个答案:

答案 0 :(得分: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
    }
}