背景
Rustにおけるmatchオペレーターは、機能型言語から借用された強力なパターンマッチングのツールです。C/C++の類似物とは異なり、Rustでは完全性チェックが厳密に行われており、すべての可能な選択肢に対して分岐が必要です。
問題
matchを使用する際のエラーは、通常、型(例えば、enum)のすべての選択肢を考慮しなかったり、ガード(分岐に対する条件)での誤った扱いや、複雑なネスト構造に関連しています。不適切な処理はコンパイル時エラーを引き起こすか、暗黙の不正なロジックにつながります。
解決策
_を使用します)。if)を付加します。コード例:
enum Shape { Circle(f64), Rectangle { width: f64, height: f64 }, } fn print_area(s: Shape) { match s { Shape::Circle(r) if r > 0.0 => println!("area = {}", 3.14 * r * r), Shape::Rectangle { width, height } if width > 0.0 && height > 0.0 => println!("area = {}", width * height), _ => println!("invalid shape"), } }
主な特徴:
match内の分岐の順序は実行に影響しますか?
はい、分岐の順序は重要です:最初の一致が見つかると、以降はチェックされません。特にパターンガードにおいては、前にガード付きの分岐があるとcatch-allの前に値をキャッチします。
enumに対するmatchで必ずcatch-all(_)が必要ですか?
いいえ、すべてのケースを明示的に列挙した場合は不要です(そして型の宣言が時間とともに変更されない限り)。しかし、追加の値が出現する可能性がある場合や、すべての分岐を明示的に処理したくない場合には必要です。
1つのmatchの分岐で複数のパターンを使用できますか?
はい。縦線(|)を使ってパターンを組み合わせることができます:
match x { 1 | 2 | 3 => println!("one, two or three"), _ => println!("something else"), }
_を使用する開発者がcatch-allを最初に置いたmatchを書き、特定のケースを正しく処理できなかった。
利点:
プログラムはコンパイルされます。
欠点:
特定のロジックが決して機能せず、一部のコードがカバーされない。
enumのすべての選択肢を明示的に処理し、catch-allは最後の分岐のみで、特定のケースには個別のガードを使用。
利点:
予測可能性、コンパイラーが選択肢を忘れないように支援し、タイプを容易に拡張。
欠点:
多くのケースがある場合、追加のテンプレートコードが必要。