ようこそ。睡眠不足なプログラマのチラ裏です。

F#でのパターンマッチ。「match a with 〜」よりも 「a |> function 〜」を使おうぜ(異論は認める)


以前、「F#では、パターンマッチを「match x with」と書く流派と「x |> function」と書く流派がございます。」という記事を書きました。
ほぼほぼ置き換えることが可能な、「match a with 〜」と 「a |> function 〜」ですが、
実は完全互換ではありません。これはカンスウガタゲンガーには割と気づきにくい違いかもしれません。
細かすぎて伝わらない程度の違いですが、カンスウガタゲンガーの@nakamura_toさんにリアクション頂いたのでちょっと書いてみます。


「match a with 〜」と 「a |> function 〜」の違い

結論から申し上げますと、functionによるパターンマッチは"クロージャー"であるということです。


「a |> function 〜」をまじまじと見つめていただくとわかるように、とてもクロージャー感を醸し出しています。
「あ〜、言われてみればそうですね。」という感じではないでしょうか。
つまり、「functionによるパターンマッチではmutableな変数をキャプチャすることができない。」という違いがあります。

module Sample =

  let hoge = 
    let hoge0 () = 
      let mutable s = "ほげ"
      match s with
      | "ふが" -> ()
      | x -> printfn "%s" s
    hoge1 ()

    let hoge1 () = 
      let mutable s = "ほげ"
      s |> function
      | "ふが" -> ()
      | x -> printfn "%s" s // mutableな変数をキャプチャできないのでエラー
    hoge1 ()

    let hoge0 () = 
      let s = ref "ほげ"
      match !s with
      | "ふが" -> ()
      | x -> printfn "%s" !s 
    hoge0 ()

    let hoge1 () = 
      let s = ref "ほげ"
      !s |> function
      | "ふが" -> ()
      | x -> printfn "%s" !s // Reference CellsはクロージャーでキャプチャできるのでOK
    hoge1 ()

    ()

open System
open Sample
hoge
Console.ReadLine () |> ignore


関数プログラミングパラダイムを主体としているカンスウガタゲンガーは、
極力 mutable を用いないプログラミングをします。mutable を利用するとしても用途はとても限定的です。
また、パターンマッチさせた値を用いずに、直接 mutable な変数をキャプチャするような書き方も好ましくないので、通常そのような書き方はしないでしょう。
ですから、このわずかな違いを意識する機会はあまりないかもしれません。
完全互換ではありませんが、一般的なカンスウガタゲンガーが書く「match a with 〜」は、ほとんどの場合「a |> function 〜」に置き換え可能でしょう。


いっそのこと、パターンマッチは「a |> function 〜」で行うように統一してしまったほうが(コーディング規約的な意味で)、
パターンマッチ内で直接 mutable な変数をキャプチャするような書き方を抑止することができるので、
カンスウガタゲンガー的にはうれしいのかもしれません(異論は認める)。
好みというよりだだの自己満ですが、「a |> function 〜」の方がイケてると思うので私は多用しまくりんぐです。



F#の勉強会とかやりたい

北海道旭川市近郊でF#の勉強をしてる人 or してみたい人いるかなあ。
もしいたら、何かコメントいただきたく。