F#明示的一致と関数構文


87

あいまいなタイトルについては申し訳ありませんが、この質問の一部は、これら2つの構文スタイルの名前です。

let foo1 x = 
    match x with
    | 1 -> "one"
    | _ -> "not one"

let foo2 = function 
    | 1 -> "one" 
    | _ -> "not one"

他の部分は、2つの間にどのような違いがあるのか​​、そしていつどちらを使用したいのかということです。

回答:


56

一致バージョンは「パターンマッチング式」と呼ばれます。関数バージョンは「パターンマッチング関数」と呼ばれます。仕様のセクション6.6.4にありますます。

どちらか一方を使用するのはスタイルの問題です。matchステートメントのみの関数を定義する必要がある場合は、関数バージョンのみを使用することをお勧めします。


ありがとうございました。F#を使用した関数型プログラミングでは、functionキーワードを使用すると、それがパターンマッチング関数であることが示されますが、この回答とOPにより、頭がおかしくなった瞬間が明らかになります。
octopusgrabbus 2018

リンクが壊れているようです。
MattMS

83

2番目の構文の長所は、ラムダで使用すると、もう少し簡潔で読みやすくなる可能性があることです。

List.map (fun x -> match x with | 1 -> "one" | _ -> "not one") [0;1;2;3;1]

vs

List.map (function 1 -> "one" | _ -> "not one") [0;1;2;3;1]

23

関数バージョンは、matchステートメントが関数全体であり、関数に引数が1つしかない(タプルは1つとしてカウントされる)特別な場合の完全一致構文の省略形です。2つの引数が必要な場合は、完全一致構文*を使用する必要があります。これは、次の2つの関数のタイプで確認できます。

//val match_test : string -> string -> string
let match_test x y = match x, y with
                        | "A", _ -> "Hello A"
                        | _, "B" -> "Hello B"
                        | _ -> "Hello ??"

//val function_test : string * string -> string                   
let function_test = function
                        | "A", _ -> "Hello A"
                        | _, "B" -> "Hello B"
                        | _ -> "Hello ??"

ご覧のとおり、match versionは2つの別々の引数を取りますが、functionversionは1つのtupled引数を取ります。関数の構文がすっきりしているので、ほとんどの単一引数関数に関数バージョンを使用します。

*本当に必要な場合は、関数バージョンに正しい型シグネチャを持たせることができますが、私の意見ではかなり醜いように見えます-以下の例を参照してください。

//val function_match_equivalent : string -> string -> string
let function_match_equivalent x y = (x, y) |> function
                                                | "A", _ -> "Hello A"
                                                | _, "B" -> "Hello B"
                                                | _ -> "Hello ??"

12

彼らはあなたの場合と同じことをします-functionキーワードfunmatchキーワードの後にキーワードが続く(匿名のラムダを生成するための)組み合わせのように機能します。

したがって、技術的には、これら2つは同じですが、fun:が追加されています。

let foo1 = fun x ->
    match x with
    | 1 -> "one"
    | _ -> "not one"

let foo2 = function
    | 1 -> "one"
    | _ -> "not one"

1
それは実際には逆ではありませんか?つまりfun、技術的に定義されていfunction | _ -> ...ますか?
Pavel Minaev 2009

1
具体的にfun x y -> ...は、、、fun x -> fun y -> ...そしてにfun x -> ...なりますfunction | x -> ...。それはあなたがでパターンマッチングを行うことができます理由ですfun例えば- fun (x::xs) -> ...
Pavel Minaev 2009

10

完全を期すために、ExpertFSharpの321ページにアクセスしました

「リスト12-2は式形式を使用していますfunction pattern-rules -> expression。これは(fun x -> match x with pattern-rules -> expression)、識別された共用体上で直接機能する関数を定義する方法と同等であり、特に便利です。」


6

関数は1つの引数のみを許可しますが、パターンマッチングを許可しますが、関数を定義するためのより一般的で柔軟な方法はfunです。ここを見てください:http//caml.inria.fr/pub/docs/manual-ocaml/expr.html


最後の引数だけでなく、1つの引数だけを言うのはなぜですか?複数の引数を持ち、「関数」を使用することが可能です。これは高階関数の解釈ですか?
シンビオント2016年

4

2つの構文は同等です。ほとんどのプログラマーはどちらかを選択し、それを一貫して使用します。

関数が動作を開始する前にいくつかの引数を受け入れる場合、最初の構文は読みやすくなります。


2

これは古い質問ですが、$ 0.02を投げます。

match「暗黙的よりも明示的の方が優れている」Pythonの世界から来たので、一般的に私はバージョンの方が好きです。

もちろん、パラメータのタイプ情報が必要な場合は、functionバージョンを使用できません。

OTOHによって作成された引数が好きなStringerのでfunction、単純なラムダで使用し始めます。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.