F#のfunction式への苦手意識が少しなくなったかもしれない
F#のmatch式、便利ですね!
let rec fib n = match n with | 0 -> 0 | 1 -> 1 | x -> fib (x - 1) + fib (x - 2)
こんな感じでパターンマッチが簡単に書けます。
さて、match式とよく似たものにfunction式というものがあります。
let rec fib = function | 0 -> 0 | 1 -> 1 | x -> fib (x - 1) + fib (x - 2)
実は私、このfunction式が苦手でして。なんかこう引数を明示しないのが気持ち悪いというか、うっかり
let rec fib n = function | 0 -> 0 | 1 -> 1 | x -> fib (x - 1) + fib (x - 2) (* これは fib n x = ~ という2引数関数だと解釈される *)
とか書いてなんか引数の数がおかしくなったりとかします。
話変わって、Haskellとかもちょこちょこ触ってたりするのですが、Haskellだとこんな感じで関数が書けます。
fib 0 = 0 fib 1 = 1 fib x = fib (x - 1) + fib (x - 2)
引数が0の時は0、1の時は1、それ以外ならほにゃららといった感じですね。個人的には割とわかりやすく感じます。
で。F#のfunction式ですが、ちょこっと書き方を変更してみます。
let rec fib = function 0 -> 0 | 1 -> 1 | x -> fib (x - 1) + fib (x - 2)
なんとなくHaskellのと似ていません?F#では
let func1 = fun x -> x + 1
という風にfun式(いわゆる無名関数)をつかっても関数を定義できますが、上のコードはfun式による「引数が0の時は0、1の時は1、それ以外ならほにゃらら」に対応したものと言えるでしょう。
(* 実際にこのようなコードを書けるわけではない *) let rec fib = fun 0 -> 0 fun 1 -> 1 fun x -> fib (x - 1) + fib (x - 2)
実は、F#のfunction式はmatch式と同じではなくて、むしろfun式のお友達です。よって
let rec fib n = match n with | 0 -> 0 | 1 -> 1 | x -> fib (x - 1) + fib (x - 2)
と
let rec fib = function 0 -> 0 | 1 -> 1 | x -> fib (x - 1) + fib (x - 2)
は微妙に意味が違っていて、前者は「fibという関数を関数定義文で定義する」であり、後者は「関数式を評価して得た関数値をfibという名前に束縛している」となります。
function式はfun式の仲間なのでこのように
[1 .. 20] |> List.map (function | x when x % 15 = 0 -> "FizzBuzz" | x when x % 5 = 0 -> "Buzz" | x when x % 3 = 0 -> "Fizz" | x -> string x)
高階関数の引数に直接書くこともできます。
そんなわけで、functionはfunの代わりだと思えば少しは苦手意識も減るかなあ、と。