簡潔性のためのパターンマッチング
これまで、 match..with
式でのパターンマッチングのロジックを見てきました。一見すると単なるswitch/case文のように見えますが、実はパターンマッチングはもっと汎用的です。値、条件、型に基づいてさまざまな方法で式を比較し、同時に値の割り当てや抽出を行うことができるのです。
パターンマッチングについては後の投稿で詳しく説明しますが、まずは簡潔性を助ける一つの方法について、簡単に紹介しましょう。 ここでは、式に値を束縛する(変数への代入に相当する関数型の方法)ためにパターンマッチングがどのように使用されるかを見ていきます。
以下の例では、タプルやリストの内部メンバーに直接束縛しています:
//タプルに直接マッチングlet firstPart, secondPart, _ = (1,2,3) // アンダースコアは無視を意味する
//リストに直接マッチングlet elem1::elem2::rest = [1..10] // 今は警告を無視してください
//match..with内でのリストマッチングlet listMatcher aList = match aList with | [] -> printfn "リストは空です" | [firstElement] -> printfn "リストには一つの要素 %A があります" firstElement | [first; second] -> printfn "リストは %A と %A です" first second | _ -> printfn "リストには2つ以上の要素があります"
listMatcher [1;2;3;4]listMatcher [1;2]listMatcher [1]listMatcher []
レコードのような複雑な構造の内部に値を束縛することもできます。次の例では、 Address
型を作成し、そのアドレスを含む Customer
型を作ります。次に、顧客の値を作成し、それに対してさまざまなプロパティをマッチングさせます。
// 型を作成type Address = { Street: string; City: string; }type Customer = { ID: int; Name: string; Address: Address}
// 顧客を作成let customer1 = { ID = 1; Name = "Bob"; Address = {Street="123 Main"; City="NY" } }
// 名前のみを抽出let { Name=name1 } = customer1printfn "顧客の名前は %s です" name1
// 名前とIDを抽出let { ID=id2; Name=name2; } = customer1printfn "%s という名前の顧客のIDは %i です" name2 id2
// 名前と住所を抽出let { Name=name3; Address={Street=street3} } = customer1printfn "%s という名前の顧客は %s に住んでいます" name3 street3
最後の例では、 Address
のサブ構造の中まで到達して、顧客名と同様に通りの名前も取り出せることに注目してください。
ネストした構造を処理し、欲しいフィールドだけを抽出し、それらを値に割り当てる、これらすべてを一度の手順で行えるこの能力は非常に便利です。かなりのコーディングの面倒さを取り除き、典型的なF#コードの簡潔性を生み出すもう一つの要因となっています。