🌽
Enum での 比較におけるPartialEqとmatchesの違い
RustのEnumで比較をする場合PartialEqを利用していましたが、matches!も比較に使えます。
比較結果が変わることがあったのでこちらで共有します。
enumの定義
最初にシンプルなenumを定義します。
enum Sports {
BaseBall,
BasketBall,
}
シンプルな比較
まずはそのまま比較します。 == と matches! 両方で試します。
let b1 = Sports::BaseBall;
// こちらはエラーです。
println!("{:?}", b1 == Sports::BaseBall);
// こちらは通る: true
println!("{:?}", matches!(b1, Sports::BaseBall));
== の比較を使いたい場合は、PartialEqを実装します。
#[derive(PartialEq)]
enum Sports {
BaseBall,
BasketBall,
}
// true
println!("{:?}", b1 == Sports::BaseBall);
// true
println!("{:?}", matches!(b1, Sports::BaseBall));
PartialEqとmatches!の違い
enumの列挙子に値を持たせる時に違いが出ます。
enum Sports {
BaseBall(i32),
BasketBall(f64),
}
以下のコードで試します。
fn main() {
let b1 = Sports::BaseBall(11);
// true
println!("{:?}", matches!(b1, Sports::BaseBall(_)));
// false
println!("{:?}", matches!(b1, Sports::BaseBall(5)));
// true
println!("{:?}", b1 == Sports::BaseBall(11));
// false
println!("{:?}", b1 == Sports::BaseBall(5));
// エラー
println!("{:?}", b1 == Sports::BaseBall(_));
}
mathces!は列挙子の値をブランク指定すると、型の比較となりtrueになります。逆にPartialEqではブランクでの比較はビルドエラーになりました。PartialEqの方が厳密な比較ですね。
面白かったのはmatches!の方で別の値を入れると、falseになります。
気になったのでexpandしてマクロを展開してみました。
fn main() {
let b1 = Sports::BaseBall(11);
{
::std::io::_print(
::core::fmt::Arguments::new_v1(
&["", "\n"],
&[
::core::fmt::ArgumentV1::new_debug(
&match b1 {
Sports::BaseBall(5) => {true},
_ => false,
},
),
],
),
);
};
}
展開したコードを見て納得ですが、パターンマッチがSports::BaseBall(5)とマッチするかを判定していたので、これはfalseになりますね。
_がパターンの値を無視しているということが理解でき、勉強になりました。
Discussion