Progrust Library.

// dictionary

match式.

match式は、対象の値を複数のパターンと上から順に照合し、最初に一致した「アーム」の処理を実行する制御フロー構文です1if式の分岐条件が論理値型の値に限られるのに対し、match式は列挙型のバリアントやリテラル値など多様なパターンで分岐できます。if式と同じくであり、実行されたアームの値がmatch式全体の値になります。

enum Ticket {
    Standard,
    Vip(i32), // 割引率(%)
}

fn describe(ticket: Ticket) -> String {
    match ticket {
        Ticket::Standard => String::from("通常チケットです"),
        Ticket::Vip(discount) => format!("VIPチケット({discount}%引き)"),
    }
}

fn main() {
    for ticket in [Ticket::Standard, Ticket::Vip(30)] {
        println!("{}", describe(ticket));
    }
}
Playgroundで開く

アームとパターン

各アームはパターン => 式,という形で書き、複数のアームを並べます。パターンは上から順に照合され、最初に一致したアームだけが実行されます。C言語のswitchと異なり次のアームへの意図しないフォールスルーは起こらず、1 | 7 => ...のように|区切りで1つのアームに複数パターンをまとめることもできます2

値を束縛するパターン

パターンの中に変数名を書くと、マッチした値(の一部)をその変数に束縛し、対応するアームの式の中で使えます。上記のTicket::Vip(discount)はその例で、Vipが保持するi32の値がdiscountという名前でアーム内から使えるようになります。

網羅性チェック

match式は対象の型が取りうる値をすべて網羅しなければならず、一致しうる値の中に処理されないものが1つでも残っているとコンパイルエラーになります3i32のように取りうる値を列挙しきれない型では、任意の値にマッチする包括パターン_などで書く)を最後に置いて残りをまとめて処理するのが一般的です。

fn describe(n: i32) -> &'static str {
    match n {
        1 => "one",
        2 => "two",
    } // エラー: E0004(あり得る値をすべて網羅していない)
}

fn main() {
    println!("{}", describe(5));
}
Playgroundで開く

補足

バリアント追加時に効く網羅性チェック

match式の網羅性チェックは、列挙型にバリアントを追加したときに真価を発揮します。追加後に対応漏れがあるmatch式ではすべてコンパイルエラーが出るため、修正が必要な箇所をコンパイラが教えてくれます。

Footnotes

  1. The Rust Reference: Match expressions — マッチ対象の値(scrutinee)を各アームのパターンと順に比較し、最初にマッチしたアームが選ばれると定義しています。

  2. The Rust Reference: Patterns - Or patterns|で複数のパターンを1つに結合できると定義しています。

  3. E0004 - Error codes indexmatch式が対象の型が取りうるすべての値を網羅していない場合に発生するエラーであると定義しています。

この辞書が使われているページ

backlinks 9

  1. 辞書if let式
  2. 辞書let-else文
  3. 辞書Option型
  4. 辞書Result型
  5. 辞書unwrap
  6. 辞書包括パターン
  7. 辞書列挙型
  8. 動かして学ぶRustプログラミング問題集 › 第11章 列挙型とmatch式
  9. 動かして学ぶRustプログラミング問題集 › 第12章 OptionとResult