Chr*_*oph 30 enums pattern-matching rust
我想申请filter一个迭代器,我想出了这个并且它可以工作,但它超级详细:
.filter(|ref my_struct| match my_struct.my_enum { Unknown => false, _ => true })
Run Code Online (Sandbox Code Playgroud)
我宁愿写这样的东西:
.filter(|ref my_struct| my_struct.my_enum != Unknown)
Run Code Online (Sandbox Code Playgroud)
这给了我一个编译错误
binary operation `!=` cannot be applied to type `MyEnum`
Run Code Online (Sandbox Code Playgroud)
有冗长模式匹配的替代方案吗?我寻找一个宏但找不到合适的宏.
Vla*_*eev 47
首先,您可以使用PartialEq特征,例如#[derive]:
#[derive(PartialEq)]
enum MyEnum { ... }
Run Code Online (Sandbox Code Playgroud)
然后你的"理想"变体将按原样运行.但是,这需要MyEnum实现内容PartialEq,这并不总是可行/想要的.
其次,你可以自己实现一个宏,就像这样(尽管这个宏不支持所有类型的模式,例如替代方案):
macro_rules! matches(
($e:expr, $p:pat) => (
match $e {
$p => true,
_ => false
}
)
)
Run Code Online (Sandbox Code Playgroud)
然后你会像这样使用它:
.filter(|ref my_struct| !matches!(my_struct.my_enum, Unknown))
Run Code Online (Sandbox Code Playgroud)
有一个RFC将这样的宏添加到标准库中,但它仍在讨论中.
您可以使用if let Some(x) = option { then }具有相同if let构造但不解构的习语:
if let Unknown = my_struct.my_enum { false } else { true }
Run Code Online (Sandbox Code Playgroud)
我会使用模式匹配,但我会将它移动到枚举上的一个方法,以便过滤器闭包更整洁:
#[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);
}
}
Run Code Online (Sandbox Code Playgroud)
也可以看看:
另一种选择是使用std::discriminant,如果您不关心匹配enum数据,这会很有用。看操场:
use std::mem;
#[derive(Debug, PartialEq, Eq)]
enum Thing {
One(i32),
Two(String),
Unknown,
}
impl Thing {
fn is_unknown(&self) -> bool {
mem::discriminant(self) == mem::discriminant(&Thing::Unknown)
}
fn is_one(&self) -> bool {
mem::discriminant(self) == mem::discriminant(&Thing::One(i32::default()))
}
}
fn main() {
let things = [Thing::One(42), Thing::Two("hello".to_owned()), Thing::Unknown];
let known_things = things.iter().filter(|&s| !s.is_unknown());
assert!(known_things.eq([Thing::One(42), Thing::Two("hello".to_owned())].iter()));
let ones = things.iter().filter(|&s| s.is_one());
assert!(ones.eq([Thing::One(42)].iter()));
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
17593 次 |
| 最近记录: |