currying - Javascript 连续调用单参函数实现任意参函数
天蓬老师
天蓬老师 2017-04-10 15:28:14
0
14
1433

函数 add 可以实现连续的加法运算
函数 add 语法如下add(num1)(num2)(num3)...;//注意这里是省略号哟,可无限

使用举例如下:

add(10)(10); // 20 add(10)(20)(50); // 80 add(10)(20)(50)(100); // 180 var add30 = add(10)(20); // 30 var add100 = add30(30)(40); // 100 var add31 = add30(1); // 31 var add40 = add31(9); // 40
天蓬老师
天蓬老师

欢迎选择我的课程,让我们一起见证您的进步~~

全員に返信 (14)
洪涛

@bf 老师的答案非常棒,学习了。不过我想@bf 老师实际上还是搞反了 currying 和 uncurrying。
currying 是将参数提前保存以在下一次调用时不必提供此参数,@bf 老师的代码所做的正是这个工作。而 uncurrying 则是将原来设定好的参数腾出来,使之可以被函数调用者重新设定。在 JavaScript 中常用于将 obj.func(x, y, z, ...)转变为 func(org, x, y, z)。这样做的好处是可以方便地应用 Duck Type
这种特性。@bf 老师后面提供的 curry 代码其实才是真正的 uncurry。(@bf 菜菜已經將自己的答案 reverse 到 r4,which fits the en wikipedia)

另,
如下代码也可以很好的工作(其实还是一种 currying,将每次的和绑定到下次调用,这样就可以连加了):

function add(x) { function helper(y, x) { var sum = y + x; var f = helper.bind(null, sum); f.toString = function () { return '' + sum; }; f.valueOf = function () { return sum; }; return f; } return helper(x, 0); } console.log(+add(10)(10)); // 20 console.log(+add(10)(20)(50)); // 80 console.log(+add(10)(20)(50)(100)); // 180 var add30 = add(10)(20); // 30 var add100 = add30(30)(40); // 100 var add31 = add30(1); // 31 var add40 = add31(9); // 40 console.log(+add30, +add100, +add31, +add40);

实际上就是要把每一次函数调用的结果都区分开而已。

いいねを押す+0
    迷茫
    javascriptfunction add(a){ function x(b){ a+=b; return x; } x.toString=function(){return a;} return x; } console.log( add(10)(10) == 20 && add(10)(20)(50) == 80 && add(10)(20)(50)(100) == 180 );// true

    返回一个返回自身的函数,就可以做到无限调用。

    いいねを押す+0
      黄舟

      reversed to r4; nonsense was deleted.

      這道題考得是柯里化。

      function curry(fn) { return function(x) { return function g(x, y) { if (y === void 0) return x; else return g.bind(this, fn(x, y)); }.bind(this, x); }; } function add(x, y) { return x + y; } var curried_add = curry(add); curried_add(1)(2)(); // 3 curried_add(1)(2)(3)(); // 6 curried_add(1)(2)(3)(); // 6 curried_add(1)(2)(3)(4)(5)(6)(7)(8)(9)(10)(11)(12)(13)(14)(15)(16)(17)(18)(19)(20)(); // 210 var a1 = curried_add(1); var a2 = a1(2); var a3 = a1(3); var a4 = a3(4); a1(), a2(), a3(), a4(); // 1 3 4 8
      いいねを押す+0
        阿神

        这个问题叫做柯里化(curry),不是勇士的库里。柯里化就是预先将函数的某些参数传入,得到一个简单的函数,但是预先传入的参数被保存在闭包中。

        具体可以看看这个实现curry

        いいねを押す+0
          小葫芦
          var add = function () { var args = [].slice.call(arguments), count = 0;  args.forEach(function (value) { count += value; }); return function () { var args = [].slice.call(arguments); if (!args.length) {return count;} args.unshift(count); return add.apply(null, args); }; }; 还可以这样调用: var add30 = add(10, 10, 10); 也可以这样调用: var add30 = add(10)(10)(10); var add100 = add30(20)(20)(30); add100(); //100
          いいねを押す+0
            Ty80

            我没记错的话这个是这题吧,原题应该是 CodeWar 上的。

            jsfunction add(n) { var temp = n; var func = function(n) { temp += n; return func; }; func.toString = func.valueOf = function() { return temp; }; return func; }
            いいねを押す+0
              大家讲道理

              首先,完全按照题目实现,根本实现不了,add(1)(2)如果返回3,add(1)(2)(3)必然报错。

              我们退一步,实现add(1)(2)()返回3,add(1)(2)(3)()返回6。

              有两种方法,第一种是每次调用都计算出中间结果,最后无参数调用时把结果返回,另一种是把加数都记下来,无参数调用时执行加法并返回。

              第一种:

              function add(a) { if (typeof a === 'undefined') { return 0; } function add_(a, b) { var s = a + b; return function (c) { if (typeof c === 'undefined') { return s; } return add_(s, c); } } return add_(0, a); } console.log(add()); console.log(add(1)(2)()); console.log(add(1)(2)(3)());

              第二种:

              function add(a) { if (typeof a === 'undefined') { return 0; } if (typeof a !== 'number') { var sum = 0; for (var i = 0; i < a.length; ++i) { sum += a[i]; } return sum; } var args = Array.prototype.slice.call(arguments, 0); return function (b) { if (typeof b === 'undefined') { return add(args); } args.push(b); return add.apply(this, args); } } console.log(add()); console.log(add(1)(2)()); console.log(add(1)(2)(3)());
              いいねを押す+0
                巴扎黑
                php
                function add(x){ var sum=x; var tmp=function(y){ sum+=y; return tmp; }; tmp.toString=function(){ return sum; }; return tmp; } console.log(add(1)(2)(3));//6 console.log(add(1)(2)(3)(4)(5));//15
                いいねを押す+0
                  巴扎黑

                  问他想考你什么
                  如果想考闭包,和函数式,和原型继承那就写给他,如果他不说
                  那么直接写个window.sum=0和function add()气死他

                  那么,就写个靠谱(~~并不靠谱,看楼上们)点的答案吧

                  1.首先需要优雅点的写法,不写成window.var,所以写个闭包

                  function foo(){ var bar=function(){} }

                  2.然后思考一下函数式累加怎么写,第一步当然是 sum=0+input;

                  function foo(x){ x=0+x; var bar=function(){}; }

                  3.这时,得把x扔进子作用域bar才行,不然就记不住这个sum了.然后进一步的累加就交由bar来处理了,理由同上.

                  function foo(x){ x=0+x; var bar=function(y){ x=x+y; }; }

                  4.再把整个结构贯通一下,先运行foo,获得result,交由bar,并且return出bar,return bar后才能继续走下一步
                  //我发现这里好像是markdown??

                  function foo(x){ x=0+x; var bar=function(y){ x=x+y; }; return bar; }

                  5.好了,现在到bar了,这就比较简单了,不用考虑闭包这无聊的事,sum_new=sum_odd + input;接着呢 还要继续累加那么,直接无限调用自身就好了,所以bar:return bar;

                  function foo(x){ x=0+x; var bar=function(y){ x=x+y; return bar; }; return bar; }

                  6.其实已经完事了,只不过为了应付原型继承这个考点,还要蛋疼的多写一步.这个也是很赖皮的..我就不想写了,反正上面代码都有了.所以我show我喜欢的写法

                  function foo(x){ x=0+x; var bar=function(y){ x=x+y; return bar; }; bar.show=function(){console.log(x);} return bar; }

                  result :foo(1)(2)(3).show() = 6

                  いいねを押す+0
                    大家讲道理
                    function add(num) { var sum = 0; function cache(arg) { if (arg === undefined) { return sum; } else { sum += arg; } return cache } return cache(num); } console.log(add(1)(2)()); console.log(add(1)(2)(4)(5)());

                    唯一的缺点,最后结束时必须再次调用一次。
                    哪位大神来完善下

                    いいねを押す+0
                      最新のダウンロード
                      詳細>
                      ウェブエフェクト
                      公式サイト
                      サイト素材
                      フロントエンドテンプレート
                      私たちについて 免責事項 Sitemap
                      PHP中国語ウェブサイト:福祉オンライン PHP トレーニング,PHP 学習者の迅速な成長を支援します!