web-dev-qa-db-ja.com

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

漠然としたタイトルについては申し訳ありませんが、この質問の一部は、これらの2つの構文スタイルが何と呼ばれるかです。

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

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

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

77
Benjol

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

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

51
gradbot

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

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

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

関数バージョンは、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 ??"

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

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

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

functionキーワードは、funキーワード(匿名のラムダを生成する)とそれに続くmatchキーワードの組み合わせのように機能します。

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

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

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

完全を期すために、私は Expert FSharp の321ページにたどり着きました:

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

9
Benjol

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

6
kamaci

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

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

4
Pascal Cuoq

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

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

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

OTOH Stringerの引数が好きなので、単純なラムダでfunctionを使い始めます。

2
Soldalma