如何在没有模式匹配的情况下比较枚举

时间:2014-08-29 21:51:43

标签: enums pattern-matching rust

我想在迭代器上应用filter并且我想出了这个并且它可以工作,但是它非常详细:

.filter(|ref my_struct| match my_struct.my_enum { Unknown => false, _ => true })

我宁愿写这样的东西:

.filter(|ref my_struct| my_struct.my_enum != Unknown)

这给了我一个编译错误

binary operation `!=` cannot be applied to type `MyEnum`

是否有替代冗长模式匹配的替代方法?我寻找一个宏但找不到合适的宏。

3 个答案:

答案 0 :(得分:40)

首先,您可以使用PartialEq特征,例如#[derive]

#[derive(PartialEq)]
enum MyEnum { ... }

那么你的理想"变体将按原样运行。但是,这要求MyEnum的内容也实现PartialEq,这并不总是可行/想要的。

其次,你可以自己实现一个宏,就像这样(虽然这个宏不支持所有类型的模式,例如,替代方案):

macro_rules! matches(
    ($e:expr, $p:pat) => (
        match $e {
            $p => true,
            _ => false
        }
    )
)

然后你会像这样使用它:

.filter(|ref my_struct| !matches!(my_struct.my_enum, Unknown))

an RFC将这样的宏添加到标准库中,但仍在讨论中。

答案 1 :(得分:3)

我使用模式匹配,但是我将它移动到枚举上的方法,以便过滤器闭包更整洁:

#[derive(Debug)]
enum Thing {
    One(i32),
    Two(String),
    Unknown,
}

impl Thing {
    fn is_unknown(&self) -> bool {
        match *self {
            Thing::Unknown => true,
            _ => false,
        }
    }
}

fn main() {
    let things = vec![Thing::One(42), Thing::Two("hello".into()), Thing::Unknown];
    for t in things.iter().filter(|s| !s.is_unknown()) {
        println!("{:?}", t);
    }
}

另见:

答案 2 :(得分:0)

您可以将if let Some(x) = option { then }习语与相同的if let构造一起使用,而无需进行破坏:

if let Unknown = my_struct.my_enum { false } else { true }