5

カリー化の概念と使用方法は知っていますが、実際にどのような価値があるのでしょうか。

4

3 に答える 3

5

関連する質問がカバーするように、カレー関数の実用的な使用?、人々がカリー化を大切にし、それを利用する理由はたくさんあります。

  • コードの再利用の改善-特殊なケースの関数は、単に部分的に適用された(そしてカレーされた)ジェネリック関数です
  • コードの読みやすさの向上-map (+2)より読みやすいmap (\x -> x + 2)
  • パフォーマンスの向上-カリー化は特定の特殊化を明らかにすることができ、優れたコンパイラーはあなたのために特殊化されたバージョンを生成します
  • 楽しい-よりシンプルなコード、より美しいコードは人生をより楽しくします。
于 2011-07-07T18:37:25.847 に答える
2

私が見つけた本当の利点:

  • バグが少ない- 関数合成によってコードを合成すると、命令型の制御フローよりも正確なコードになる傾向があります。たとえば、「for ループ」ではなく「map」を使用すると、多くの「off by one」インデックス作成エラーのリスクを排除できます。

  • 並行性の向上- 純粋で副作用のない関数で作成したコードは、自動的にスレッド セーフになります。これを不変の永続的なデータ構造と組み合わせると、堅牢な並行コードを作成するための優れたレシピが得られます。Clojure はこれに特に適しています。http://www.infoq.com/presentations/Value-Identity-State-Rich-Hickeyを参照してください。

  • より簡潔で管理しやすいコード- 私の完全に非科学的な分析では、機能的なコードは命令型の OOP コードよりもかなり短いようです。この利点は、プログラムが大きくなるにつれて顕著になる傾向があります。これにはいくつかの理由があると思います:

    • 関数型言語の構文はかなり簡潔になる傾向があります。たとえば、Haskell とさまざまな Lisp はどちらも、非常に単純で洗練された構文を持っています。
    • 関数型言語は、プログラムの一部を「接着」するのではなく、(高次関数の) 構成を促進する傾向があります。したがって、他の多くのパラダイムに固有のボイラープレートの多くを回避します。
    • 構成点に関連して、DRY 原則を関数型言語に適用する方が簡単であることがわかりました。共通のパターンが見られる場合は、ほとんどの場合、これを高階関数 (または Lisper の場合はマクロ) に簡単に抽出して、他の場所で使用できるようにすることができます。
  • テスト容易性 - 主に純粋な関数を使用してコードを作成すると、堅牢なテストを簡単に作成できます。

もちろん、これを相殺するためのいくつかの欠点があります。

  • 書くのは難しいです。かなり複雑な抽象的な概念を頭の中に保持する必要があるため、精神的な敏捷性が必要です。あなたが訓練された数学者であれば役に立ちますが (私はそうです)、関数型のコードを書くことは OOP より難しいと思います。
  • パフォーマンスのオーバーヘッドがいくらかあります。関数型言語は、必然的にある程度のオーバーヘッドを意味するさまざまな構造を使用します。これは優れたコンパイラでかなり小さくすることができますが、完全に排除することはできません。
  • ライブラリ/ツールのサポート - これはほぼ完全に OOP プラットフォームとツールの成熟度の向上によるものですが、それでもなお問題です。長期的にはこれは問題にはなりませんが、私が見つけた最善の解決策は、Clojure を使用することです。Clojure は、ほとんどの Java プラットフォーム ライブラリとツールから恩恵を受けることができます。
于 2011-07-06T08:14:15.720 に答える
1

ワンス・アンド・オンリー・ワンスに少し似ていると思います

C/C++ では、次のようなコードを書いています。

configure_grid (grid, first_column, last_column, action) {
    for (i = first_column; i <= last_column; ++i)
        // ...
}

configure_grids (action) {
   congifure_grid (alpha, first_alpha, last_alpha, action);
   congifure_grid (beta, first_beta, last_beta, action);
}

アルファとベータのそれぞれに対して for ループを 1 回記述する代わりに。これは、手続き型コードのカリー化に似ています。ここでの利点は明らかです。

カリー化は重要な理論的概念ですが、実際には、これが利点です。

実際、C でテスト スイートを書いたことがあるのを覚えています。

typedef bool (*predicate) (const type *);

const char * argument;

bool do_foo (const type * t) {
    return bar (t, argument);
}

bool do_baz (const type * t) {
    return bap (t, argument);
}

predicate foo (const char * arg) {
    argument = arg;
    return do_foo;
}

predicate baz (const char * arg) {
    argument = arg;
    return do_baz;
}

assert (for_all (data_set("alpha"), foo ("abc")));
assert (for_all (data_set("beta"),  baz ("def")));

これはすべて純粋な C であり、マクロのトリックなどはありません。関数型スタイルで、カリー化のようなものです。ここでの利点は、テスト ケースが何であるかを一目で正確に確認できることです。data_set似ています -- データを取得する別の関数に引数をバインドします:for_allサンクを実行し、述語をチェックし、クリーンアップします。几帳面。

于 2011-07-06T08:26:13.813 に答える