イテレータに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`
詳細なパターンマッチングの代替手段はありますか?マクロを探しましたが、適切なマクロが見つかりませんでした。
まず、PartialEq
traitを使用できます。たとえば、#[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))
このようなマクロを標準ライブラリに追加する RFC がありますが、まだ検討中です。
パターンマッチングを使用しますが、enumのメソッドに移動して、フィルタークロージャーがよりきれいになるようにします。
#[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);
}
}
こちらもご覧ください: