JavaScript 関数プログラミングでのカリー実装

黄舟
リリース: 2017-03-02 14:53:09
オリジナル
1382 人が閲覧しました

最近、私は JavaScript の関数プログラミングを学んでいます。そして、有名なカリー関数にとても興味があります。カリー関数は関数を受け取ることができ、とりあえずオリジナルの関数と呼ぶことにします。これは関数、カリー化された関数を返します。この関数は非常に強力で、実行プロセス中、元の関数の実行条件がトリガーされるまで、渡されたパラメーターを格納する関数を返し続けます。これはより一般的なので、説明するために例を示します:

元の関数:

var add = (x, y) => x + y
ログイン後にコピー

カリー化された関数:

 var curryAdd = curry(add)
ログイン後にコピー

この追加には 2 つのパラメーターが必要ですが、curryAdd の実行では、渡されるパラメーターの数が少ない場合、より少ないパラメーターを渡すことができます。 add で必要なパラメータ以外の場合、add 関数は実行されません。curryAdd はパラメータを書き留め、別の関数を返します。この関数は、渡されたパラメータを引き続き実行できます。特別に、受信パラメータの状況を記録します。受信パラメータの合計数が add で必要なパラメータの合計数と等しい場合、元のパラメータの実行がアクティブになり、必要な結果が返されます。

// 此时只传入了一个参数 根据判断返回的是一个函数
    var add2 = curryAdd(2)
    // add2 = function(...) {}
ログイン後にコピー
rree

かなり良いですよね? さて、私たちの目標はこの魔法のカレー関数を書くことであり、それを 1 行で記述する必要があります。心配しないで、最初にその書き方を分析してから、段階的に最適化していきます。 。

上記の説明に基づいて、curry 関数に必要なものを見てみましょう。まず、関数には length という属性があることがわかります。それを保存するには、limit を使用します。

// 此时累计传入了两个参数 等于了add需要参数的总和 所以返回的是一个结果
    // 相当于执行了add(2)(3)
    var result = add2(3)
    // result = 5
ログイン後にコピー

カレー関数は、実行する必要がある関数を返す必要があります。問題は、この関数の実行が元の関数の実行をアクティブにするかどうかを判断する必要があることです。渡されるパラメータ。関数または結果を返しますか?これは確かに問題です。渡されたパラメータが元の関数に必要なパラメータと等しい場合は、元の関数 fn

    var curry = function(fn) {
         var limit = fn.length
         ...
    }
ログイン後にコピー

を実行する必要があります。パラメータは 2 つあります。1 つは渡されたパラメータの履歴を記録する必要があること、もう 1 つは返された関数が何をする必要があるかです

    var curry = function(fn) {
         var limit = fn.length
         return function (...args) {
             if (args.length >= limit) {
                 return fn.apply(null, args)
             }
         }
    }
ログイン後にコピー

ご存知のとおり、必要なのは、返された関数の実行パラメータを蓄積することだけです。渡されたパラメータを記録する この状況の目的のために、返す関数がしなければならないことは、上記のことを繰り返すことであり、これが関数の目的です。パラメータ args が行う必要があるため、名前が必要です。そうでないと実行できません。これを judgeCurry と呼びます

したがって、前述したように、関数を返すか、元の関数を実行します。

rreee

この魔法のカレー関数をついに書き終えました。Compose と組み合わせると、本当に強力になります。

私たちの目標は、上記の関数を 1 行で書くことです。書き方?ちなみに、私はES6を使用しているので、かなりの時間を費やしました

    var curry = function(fn) {
         var limit = fn.length
         return function (...args) {
             if (args.length >= limit) {
                 return fn.apply(null, args)
             } else {
                 return function(...args2) {

                 }
             }
         }
    }
ログイン後にコピー

さて、何が問題なのか見てみましょう ちなみに、limitパラメータを使用しないようにするには、使用時に値を割り当てる必要があります。このように、

    var curry = function(fn) {
         var limit = fn.length
         return function judgeCurry (...args) {
             if (args.length >= limit) {
                 return fn.apply(null, args)
             } else {
                 return function(...args2) {
                     return judgeCurry.apply(null, args.concat(args2))                                     
                 }
             }
         }
    }
ログイン後にコピー

はパラメータを判定する際に常にfn.lengthを評価する必要がありますが、fn.lengthの値は確定したくないのです。毎回ですが制限を使いたくないのですがどうすればよいですか?この関数をすぐに実行することを考えたに違いありません。 !

var currySingle = fn => judgeCurry = (...args) => args.length >= fn.length ? fn.apply(null, args) : 
(...args2) => judgeCurry.apply(null, args.concat(args2))
ログイン後にコピー

JavaScript の魔法にため息をつくしかありません。ついに、この魔法のカレーを一行で書き上げました。

上記は JavaScript 関数プログラミングでのカレー実装の内容です。さらに関連する内容については、PHP 中国語 Web サイト (www.php.cn) をご覧ください。

関連ラベル:
ソース:php.cn
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
最新の問題
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート