パターンマッチ2
パターンマッチ1で紹介した基本的な定数へのパターンマッチの他に
F#では様々なパターンマッチを記述出来ます。
ここでは、残りのパターンについて説明します
判別共用体パターン(Discriminated Union Patterns)
OCamlではヴァリアントと呼んでいるもので
C言語ではunionに相当するパターンです。
各々の型名の
先頭の文字は大文字である必要があります。
Discriminated Union Pattern
type VARIABLE =
| INT of int
| FLOAT of float;;
let var1 = INT(10);;
let var2 = FLOAT(20.);;
let doubleexp var =
match var with
| INT(x) -> x * 2
| FLOAT(x) -> int (x * 2.);;
printfn "%d" <| doubleexp var1;;
printfn "%d" <| doubleexp var2;;
これの賢い使い方として、
最後にワイルドカードパターンにあたるものを置かない
というやり方があります。
そうすれば、網羅していないパターンをコンパイラが教えてくれるため
バグが起きる可能性が減ります。
例えば上の例であれば、INTとFLOATのケースだけパターンマッチすれば
ワイルドカードパターンを置く必要がないのは明らかです
Literal Patterns
[<Literal>]属性をつけると
letで定義した値をパターンにすることができます。
これを名前付きリテラルと呼びます。
名前つきリテラルは、必ず大文字で始める必要があります。
参考
以下の例では、通常はOminous変数が全てのパターンにマッチするため
_の行はパターンマッチしないはずですが
Ominous変数にはLiteral属性がついているため
きちんとパターンマッチします。
サンプルの例を本当なら(13,"Fri")としたかったのですが
タプルにはまだ対応していないようです(バージョン6.0時点)
Literal Pattern
[<Literal>]
let Ominous = 13;;
let isJasonSafetyFriday day =
match day with
| Ominous -> false
| _ -> true in
printfn "%b" <| isJasonSafetyFriday 13
As patterns
パターンに別名をつけるパターンです。
パターン -> 式のような形で、
パターンが複合型かつ、式で何回か使い回すような場合に使うと
記述がすっきりします。
以下、F# 4.1 spec 7.3に載ってた例そのまま
AsPattern
let t1 = (1,2)
let (x,y) as t2 = t1
printfn "%d-%d-%A" x y t2 // 1-2-(1,2)
Union patterns
複数のパターンに一度にマッチさせるパターンです。
以下はフィボナッチ数の定義に用いた例です。
C言語のswitch文でいえばbreakを書かずに複数のcase文を並べているのに相当します。
UnionPattern
let rec fib n =
match n with
| 1 | 2 -> 1
| x -> (fib <| n - 1) + (fib <| n - 2) in
print_int <| fib 10;;