次にマルチケースアクティブパターンの例を挙げてみます。
//マルチケースアクティブパターン
let (|Even|Odd|) n = //※1
if n % 2 = 0 then Even
else Odd
//パターンマッチ
let testNum x =
match x with //※2
| Even -> printfn "given value %d is Even" x
| Odd -> printfn "given value %d is Odd" x;; //※3
testNum 3 //※4
testNum 4;;
▼
val ( |Even|Odd| ) : int -> Choice<unit,unit> val testNum : int -> unit > given value 3 is Odd given value 4 is Even
上記のリストの(※1)は引数nが偶数のときEven、奇数のときOddにnを分類するアクティブパターンです。※2のパターンマッチングで使用され、引数nをアクティブパターンに渡して処理をしてからパターンマッチングを行いします。testNum 3(※4)が実行されると、まず引数n(3)がアクティブパターンに引数として渡されます。n%2=1となり、アクティブパターンはnをOddに分類します。そのため、※2のパターンマッチでは、Oddのパターン(※3)が選択され処理されます。
上記の例は、引数として入力されるデータが全ていずれかのアクティブパターン識別子に分類されることを前提としていますが、実際にはそうではありません。ある種のデータのみに該当処理をして各アクティブパターン識別子に分類したいが、”それ以外”として分類したいデータがある(つまりマッチングが失敗する可能性がある)というアクティブパターンを設定することが可能で、そのようなアクティブパターンをパーシャルアクティブパターンと呼びます。
-------------------------------------------- let (|アクティブパターン識別子|_|) [ 引数 ] = 式 --------------------------------------------
アクティブパターン識別子の最後に|_|を追記し、式にも該当パターンがなかった場合の処理を追記します。パーシャルアクティブパターンはオプション型の値を返します。つまり、戻り値はSome(値)もしくは、Noneになります。
//パーシャルアクティブパターン
let (|Multiple3|_|) n = //※1
if n % 3 = 0 then Some(n)
else None
let (|Even|_|) n =
if n % 2 = 0 then Some(n)
else None
//パターンマッチ
let testNum1 x = //※2
match x with
| Multiple3 y & Even z -> printfn "%d is divisible by 3 and 2." x
| _ -> printfn "%d is not divisible by 2 or %d is not divisible by 3" x x
testNum1 3
testNum1 4
testNum1 6;;
▼
3 is not divisible by 2 or 3 is not divisible by 3 4 is not divisible by 2 or 4 is not divisible by 3 6 is divisible by 3 and 2. val ( |Multiple3|_| ) : int -> int option val ( |Even|_| ) : int -> int option val testNum1 : int -> unit
上記のリストでは、まずパターンマッチ(※2)で最初に出てくるMultiple3のアクティブパターンが引数を渡した時、ヒットするかどうかを確認します。アクティブパターンは引数が3の倍数の時、値はマッチを見つけMultiple3に分類され、値を返します。それ以外のとき、つまり指定された他のパターンがヒットしない場合、検索に失敗した場合にはNoneを返します。
その次に、パターンマッチは、アクティブパターンEvenに引数を渡したときヒットするかどうかを確認します。アクティブパターンは値が2の倍数のときはEvenに分類され値を返し、それ以外の場合はNoneを返します。2つのアクティブパターンがともにtrueの場合には値がdivisible by 3 and 2と表示されます。
