How to compare enum without pattern matching
EnumsPattern MatchingRustEnums Problem Overview
I want to apply filter
on an iterator and I came up with this one and it works, but it's super verbose:
.filter(|ref my_struct| match my_struct.my_enum { Unknown => false, _ => true })
I would rather write something like this:
.filter(|ref my_struct| my_struct.my_enum != Unknown)
This gives me a compile error
binary operation `!=` cannot be applied to type `MyEnum`
Is there an alternative to the verbose pattern matching? I looked for a macro but couldn't find a suitable one.
Enums Solutions
Solution 1 - Enums
Use matches!
, e.g.:
matches!(my_struct.my_enum, Unknown)
Alternatively, you can use PartialEq
trait, for example, by #[derive]
:
#[derive(PartialEq)]
enum MyEnum { ... }
Then your "ideal" variant will work as is. However, this requires that MyEnum
's contents also implement PartialEq
, which is not always possible/wanted.
Solution 2 - Enums
I'd use pattern matching, but I'd move it to a method on the enum so that the filter closure is tidier:
#[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 = [Thing::One(42), Thing::Two("hello".into()), Thing::Unknown];
for t in things.iter().filter(|s| !s.is_unknown()) {
println!("{:?}", t);
}
}
You can combine this with the matches
macro as well:
fn is_unknown(&self) -> bool {
matches!(self, Thing::Unknown)
}
See also:
Solution 3 - Enums
You can use if let Some(x) = option { then }
idiom with the same if let
construct but without destructuring:
if let Unknown = my_struct.my_enum { false } else { true }