4

私はF#が初めてです。私が最初に気づいたことの 1 つは、コレクション操作がメソッドではなく関数として定義されていることです。

実験として、次の 2 つのメソッドを定義しましたlist

type List<'a> with
    member this.map f = List.map f this
    member this.filter f = List.filter f this

次に、これらのヘルパーが与えられた場合:

let square x = x * x

let isEven n = n % 2 = 0

メソッドの使用例を次に示します。

[1 .. 10].filter(isEven).map(square)

そして、ここに伝統的な方法があります:

[1 .. 10] |> List.filter isEven |> List.map square

したがって、簡潔さがメソッドよりも関数を選択する理由ではないことは明らかです。:-)

ライブラリ設計の観点から、メソッドではなく関数が選ばれたのはなぜですか?

私の推測では、パスアラウンドは可能ですが、メソッドをリストに「結び付ける」か、無名関数でラップしない限り (つまり、メソッドを実質的に関数 on に戻さない限り)、メソッドをList.filter実際にパスすることはできません。filter(fun (ls : 'a list) -> ls.filter)filterlist

ただし、その理由があっても、操作を直接呼び出す最も一般的なケースでは、メソッドの方が簡潔であるため、メソッドが優先されるようです。ということで、他に理由があるのでは?と思います。

編集:

私の 2 番目の推測は、関数の特殊化です。つまり、特化するのは簡単ですList.filter(例: let evens List.filter isEven)。メソッドを定義する必要がある方が冗長に思えますevens

4

2 に答える 2

6

関数がメソッドよりも優れているのは、関数の特殊化とそれによって可能になる簡単な因数分解です。

関数を含む式の例を次に示します。

let square x = x * x

let isEven n = n % 2 = 0

[1 .. 10] |> List.filter isEven |> List.map square

evensイベントをフィルタリングするために呼び出される関数を取り出してみましょう。

let evens = List.filter isEven

それでは、int のリストを 2 乗する関数を因数分解してみましょう。

let squarify = List.map square

元の式は次のようになります。

[1 .. 10] |> evens |> squarify

元のメソッド ベースの式に戻りましょう。

[1 .. 10].filter(isEven).map(square)

この場合、イベントに対するフィルターの因数分解は簡単ではありません。

于 2013-02-27T14:13:35.663 に答える
4

あなたの推測は正しいと思います。簡潔さはさておき、List.filter渡され (最初の推測)、部分的に適用される (2 番目の推測) 可能性があるファースト クラスのものとして扱うことができることが重要です。それは、世界を見る名詞指向の方法ではなく、動詞指向の方法です。Steve Yegge が一番うまく言ったと思います:)

于 2013-02-27T18:26:17.193 に答える