if/elif/else式を使うと、条件に応じて処理を実行できます。F#には、条件に応じて処理を実行するための、より強力な方法がもう1つあります。それがパターンマッチングです。パターンマッチングを使うと、ある値が1つ以上の_パターン_に当てはまるかどうかを調べられます。そのようなパターンの1つに、定数パターンがあります。これは、値が定数(たとえば1や"hello")と一致するかどうかを調べるパターンです。
F#では、パターンマッチングはmatchキーワードを使って行います。
let describe number =
match number with
| 0 -> "Zero"
| 1 -> "One"
これは他の言語のswitch文に似ているように見えるかもしれませんが、他のパターンも組み合わせると、パターンマッチングの真価が発揮されます。その1つが変数パターンで、これを使うと値を取り出せます。
match number with
| 0 -> "Zero"
| i -> sprintf "Non zero: %d" i
場合によっては、パターンにさらに条件を加えたいことがあります。これは_ガード_節と呼ばれ、whenキーワードを使って追加できます。
match number with
| 0 -> "Zero"
| i when i < 0 -> "Negative number"
ガード節には、関数の呼び出しを含め、有効な式であれば何でも書けます。
上の例では、すべての入力に一致するパターンがあるわけではありません。コンパイラーはこれを検出し、警告を出力します。これは網羅的なマッチングと呼ばれます。警告を解消するには、すべてのケースを処理する必要があります。そのために使えるのが[ワイルドカードパターン][wildcard-pattern]で、これはどの値にも一致するパターンです。
match number with
| i when i < 0 -> "Negative number"
| _ -> "Positive number"
// No compiler warning
コンパイラーはwhen節を使って網羅性を推論することはできない点に注意してください。
match number with
| i when i < 0 -> "Negative number"
| i when i >= 0 -> "Positive number"
// Compiler warning
パターンマッチングでは、値が上から順に各パターンと照合され、一致するパターンが見つかると、そのパターンに対応する処理が実行されます。パターンの順番は重要です! そのため、破棄パターンは必ずmatch式の最後のパターンにします。
パターンマッチングは非常に強力ですが、単純な条件分岐なら、ふつうはif/else式を使ったほうが明確に書けます。
let usingPatternMatching number =
match number with
| 0 -> "Zero"
| _ -> "Non-zero"
let usingIfElse number = if number = 0 then "Zero" else "Non-zero"