match式の概要
これまで他の章のサンプルコードで、match式について特に触れずに利用しているサンプルを多用してきました。それほどmatch式は、F#コーディングに深く根付いている最重要機能の一つです。C#でいうところのswitch-case文のようなものです(C#8.0から導入されるswitch式は、このmatch式と近い機能を持っています)。もう少しざっくりと言うならば、高機能版if式みたいなものです。
しかし、F#のmatch式はC#のswitch-case文よりも遥かに強力です。match式は、テスト式と一連のパターンとの比較に基づいて複雑な分岐を可能にします。与えられた値をもとにテスト式を各パターンと順番に比較していき、一致するパターンが見つかった場合に、対応する式(= result-expression)が評価され、その値が結果として返されます。これをパターンマッチング、またはパターンマッチと言います。
パターンマッチは、match式やfunction式などを利用して行われます。これらは、bindingやラムダ式、式に関連づいている例外処理などの引数を処理する際に利用されます。
以下はmatch式の基本となる構文です。
// ------------------
// [ 構文 ]
// ------------------
match test-expression with
| pattern1 [ when condition ] -> result-expression1
| pattern2 [ when condition ] -> result-expression2
| ...
各パターンは、何らかの方法で入力を変換するための「変換ルール」として機能します。match式は、入力データのパターンが定義されている各パターンと一致するか順番に検査していきます。一致したパターンが見つかると、それに紐づく結果式(= result-expression, 実行式ともいう)が実行されます。また、パターンマッチした値に対してさらに条件を課したい場合には whenキーワード を利用することで、詳細な分岐が可能となっています。以下はパターンマッチの一覧です。
パターン名 | 説明 | 例 |
---|---|---|
定数パターン | 任意の数値、文字、文字列リテラル、列挙定数、または定義済みリテラル識別子とのパターンマッチング. | 1.0 "hoge" Color.Red |
識別子パターン | 判別共用体のケース値、例外ラベル、またはアクティブパターンのケースでのパターンマッチング. | Some(x) Failure(msg) |
変数パターン | 照合される値をパターンに則り、新たに変数に割り当てるようなパターンマッチング. | var1 |
asパターン | 照合する値をmatch式の結果式で使用できる値にバインディングするようなパターンマッチング. | (a, b) as tuple1 |
ORパターン | 論理演算 OR を利用した複合条件でのパターンマッチング. | ([h] | [h; _]) |
ANDパターン | 論理演算 AND を利用した複合条件でのパターンマッチング. | (a, b) & (_, "foo") |
Consパターン | リストの先頭要素と残りの要素に分離させるようなパターンマッチング. | x::xs |
リストパターン | リストの要素数でのパターンマッチング. | [ a; b; c; ] |
配列パターン | 配列の要素数でのパターンマッチング. | [| a; b; c; |] |
かっこで囲まれたパターン | 結合規則を制御するためのパターン. | ( a ) |
タプルパターン | タプルとのパターンマッチング. (pattern_1, ..., pattern_N) | (a, b) |
レコードパターン | レコードを分解してフィールドを抽出するためのパターン. | { Name = name; Age = age; } |
ワイルドカードパターン | すべての値とパターンマッチングするパターン. | _ |
型注釈パターン | 値の型が指定されているパターンマッチング. | a : int |
型テストパターン | 入力値を特定の型と照合するためのパターンマッチング. | :? System.DataTime as dt |
nullパターン | 入力値がnullか照合するためのパターンマッチング. | null |
サンプルでみるmatch式
まずは、以下の簡単な例を見てみてください。
printList関数は list型 を引数に取り、そのlistの要素をすべて出力する関数です。その処理の中で、引数のリストに対してパターンマッチングを行っています。
処理の中身も簡単で、リストをheadとtailに分けられる内はheadの内容を表示していき、空リストになったら空文字を表示して処理を終了します。この「headとtailに分けられる」や「空リストの場合」などの条件がいわゆる "パターン" です。そしてそれにマッチした場合に、それに紐づけられている処理を実行します。
使い方は非常にシンプルなので、覚えることにそれほど苦労はないと思います。また、パターンマッチにはマッチングのさせ方によっていくつか名前が付けられていますが、基本的な考え方は変わりません。次章以降で各パターンマッチの方法について紹介したいと思います。