ProgrammingRust開発者

Rustにおけるパターンマッチングとデストラクチャリングはどのように機能し、それらを使用する際に考慮すべき注意点は何ですか?

Hintsage AIアシスタントで面接を突破

回答

パターンマッチングはRustの機能で、値を構造に基づいて分解し、matchif letwhile 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;

注意点:

  • refref mutを使うことで分解時に参照を得ることができます。
  • @を使ってパターンの一部を「再命名」することができます。
  • 値、範囲、条件(if guard)に基づいたマッチング。
  • 参照をデストラクチャリングする際(&SomeType)は、所有権と借用に注意が必要です。

隠れた質問

常に「_」(アンダースコア)を使用してパターンの一部を無視し、コンパイラの警告を回避できますか?

必ずしもそうではありません。アンダースコアは値をスキップしますが、enumのすべてのバリエーションを処理しないまま「_」を使ってキャッチオールを使用すると、将来的にenumが拡張された際に新しいバリエーションの処理を見逃す可能性があります。必ず重要なバリエーションを明示的に列挙して、コンパイラに未処理のケースについて警告させるのがベストです!

match result { Ok(val) => ..., Err(err) => ..., //_ => ... // enumには推奨されません! }

このトピックの知識不足による実際のエラーの例


ストーリー

IoTアプリケーションで、新しいenumバリエーションをパターンマッチングに追加したところ、「_」を使用していたためデバイスが応答しなくなりました。エラーはデプロイまで隠れていました。それ以来、重要なenumは常に明示的にバリエーションを列挙して処理されることになりました。


ストーリー

ネストされたタプルを持つ複雑な構造体について、再帰的フィールドのデストラクチャリング構文を追加するのを忘れたため、参照を取得するのではなく、大きなオブジェクトを誤ってクローンしてしまい、パフォーマンスが低下しました。


ストーリー

スレッド間のメッセージ送信機能の中で、if-letを使用してデストラクチャリングを行ったが、rareなenumバリエーションを無視していました。新しいビジネスロジックが追加されるとメッセージが失われてしまいました。それ以降、チームスタイルでは各match表現はキャッチオールなしで完全であるべきというルールが定められました。