パターンマッチングはRustの機能で、値を構造に基づいて分解し、match、if let、while letを使用して複雑な型を解析・処理することができます。デストラクチャリング(部分に分解すること)は、タプル、構造体、enum、さらには参照を扱うのに便利です。
enumを使った例:
enum Message { Quit, ChangeColor(i32, i32, i32), Write(String), } let m = Message::ChangeColor(255, 0, 0); match m { Message::Quit => println!("Quit!"), Message::ChangeColor(r, g, b) => println!("Color: {} {} {}", r, g, b), Message::Write(text) => println!("Text: {}", text), }
構造体のデストラクチャリング:
struct Point { x: i32, y: i32 } let p = Point { x: 10, y: 20 }; let Point { x, y } = p;
注意点:
refやref mutを使うことで分解時に参照を得ることができます。@を使ってパターンの一部を「再命名」することができます。if guard)に基づいたマッチング。&SomeType)は、所有権と借用に注意が必要です。常に「_」(アンダースコア)を使用してパターンの一部を無視し、コンパイラの警告を回避できますか?
必ずしもそうではありません。アンダースコアは値をスキップしますが、enumのすべてのバリエーションを処理しないまま「_」を使ってキャッチオールを使用すると、将来的にenumが拡張された際に新しいバリエーションの処理を見逃す可能性があります。必ず重要なバリエーションを明示的に列挙して、コンパイラに未処理のケースについて警告させるのがベストです!
match result { Ok(val) => ..., Err(err) => ..., //_ => ... // enumには推奨されません! }
ストーリー
IoTアプリケーションで、新しいenumバリエーションをパターンマッチングに追加したところ、「_」を使用していたためデバイスが応答しなくなりました。エラーはデプロイまで隠れていました。それ以来、重要なenumは常に明示的にバリエーションを列挙して処理されることになりました。
ストーリー
ネストされたタプルを持つ複雑な構造体について、再帰的フィールドのデストラクチャリング構文を追加するのを忘れたため、参照を取得するのではなく、大きなオブジェクトを誤ってクローンしてしまい、パフォーマンスが低下しました。
ストーリー
スレッド間のメッセージ送信機能の中で、if-letを使用してデストラクチャリングを行ったが、rareなenumバリエーションを無視していました。新しいビジネスロジックが追加されるとメッセージが失われてしまいました。それ以降、チームスタイルでは各match表現はキャッチオールなしで完全であるべきというルールが定められました。