パターンマッチングはRustにおいて非常に重要な言語機能で、関数型言語から導入されました。これは、宣言的で簡潔かつ安全に、複雑な値の変種を分析することを可能にし、ガード式を用いることで条件を追加することで、ロジックに対して柔軟性と制御を提供します。
排他性チェック(exhaustiveness checking)がないと、パターンマッチングの機能の一部がエラーを引き起こす可能性があります。さらに、分岐の順序やガード式を理解していないと、ロジックやパフォーマンスの誤りを犯す可能性があります。
Rustでは、コンパイラが全てのenumのバリエーション(またはより単純なパターン構造)が解析されているか、ワイルドカード _ の分岐があることを確認します。この分岐は追加の制約としてガード式(パターンの後の if)で制限される場合があり、その条件が満たされたときのみ「発動」します。残りのバリエーションはキャッチされません。分岐の順序は重要で、上から下へとチェックされます。
コード例:
enum Message { Hello, Data(i32), Quit, } fn handle(msg: Message) -> &'static str { match msg { Data(n) if n > 10 => "Big Data", Data(_) => "Some Data", Hello => "Greet!", Quit => "Bye", } }
主な特徴:
パターンが一致した場合、しかし条件が満たされなかったとき、ガードを含む分岐は発動しますか?
いいえ、その場合、次の適合する分岐にチェックが移ります。パターン + ガードは原子的な「フィルタ」であり、両方が一致したときにのみ、その分岐のボディが実行されます。
matchの分岐の順序はパフォーマンスに影響しますか?
はい。特にガードを持つ類似のパターンが多数存在する場合、コンパイラは上から下へと分岐をチェックするため、ランタイムでのチェック速度に影響を与えます。より頻繁に出現する値を前に処理する方が良いです。
排他性チェックを省略し、単に _ の分岐だけを置くことはできますか?
技術的には可能ですが、信頼性が失われます: もし型が新しい要素を排除(または追加)しても、コンパイラは未処理のケースについて警告しません。重要なケースは常に明示的に処理し、_ はあくまで最後の手段とすべきです。
_ に流し込むべきではありません。ガード式を持つenumのためのmatchコードで、ガードのあるパターンが最後に来ており、大部分の値が早期の _ 分岐を通過して必要な処理に達しないケース。
利点:
_ の形で「仮の処理」を迅速に実装できます。欠点:
まず、最も頻繁かつ重要なバリエーション(ガード付き)を列挙し、次に他のバリエーションを排他的にカバーします — _ への余分なコードなしで。
利点:
欠点: