曾经,我非常羡慕那些人见人爱的人,我也想要变成那样,可是后来我才明白人见人爱也是需要天赋的,后来我开始默默努力,我想,就算我不能让每个人都喜欢我,至少因为我做的努力能得到别人的尊重。

柯里化

什么是柯里化? 

  f(x)和g(x)合成为f(g(x)),有一个隐藏的前提,就是f和g都只能接受一个参数,如果可以接收多个参数,比如 f(x, y) 和 g(a, b, c),函数合成就非常麻烦了。 

  这时就需要使用到函数柯里化了,所谓的“柯里化”,就是把一个多参数的函数,转化为单参数函数。如下:

// 柯里化之前
function add(x, y) {
  return x + y;
}

add(1, 2) // 3

// 柯里化之后
function addX(y) {
  return function (x) {
    return x + y;
  };
}

addX(2)(1) // 3

   有了柯里化之后, 我们就能够做到,所有函数都只接受一个参数。 

 

 

   






 

 

  函数柯里化又称为部分求值,就是不会立即求值,而是等到了需要的时候再去求值

 

  有这样的一个场景,记录程序员一个月的加班总时间,那么好,我们首先要做的就是记录程序员每天加班的时间,然后把一个月中每天加班的时间相加,这样,就得到了一个月的加班总时间。 

 


问题来了,我们又很多方法来实现,比如最简单的:

    var monthTime = 0;
    function overtime(time) {
      return monthTime += time;
    }

    overtime(3.5); // 第一天
    overtime(4.5); // 第二天
    overtime(2.2); // 第三天
    //...
    //
    //
    //
    overtime(3.2); // 第三十天

    console.log(monthTime);

这个思路应该是最简单的,就是一个函数,变量时monthTime,每天加上加班小时数之后返回总的加班时间。   

每次传入加班时间都进行累加,这样当然没问题,但你知道,如果数据量很大的情况下,这样会大大牺牲性能。

 

那怎么办?这就是柯里化要解决的问题。

 

其实我们不必每天都计算加班时间只需要保存好每天的加班时间,在月底时计算这个月总共的加班时间,所以,其实只需要在月底计算一次就行

即对于每次输入的时间,我们只需要保存起来即可,这样,没有了加法返回的步骤,就可以减少运算了。 

如下所示的overtime函数还不是一个柯里化函数的完整实现,但是可以帮助我们了解其中的核心思想了:

这里的思想非常简单, 就是如果传入了参数,那么就把这个参数push到args数组中,表明这是在累加的阶段; 如果没有传入参数,那么就说明已经加完了,只要最后一次求和即可。  关键是这个overtime函数返回的是一个函数。  这里需要注意。如下:

  var overtime = (function () {
      var days = [];
      return function () {
        if (arguments.length == 1) {
          [].push.apply(days, arguments);
        } else {
          var total = 0;
          for (var i = 0; i < days.length; i++) {
            total += days[i];
          }
          console.log(total);
          return total;
        }
      }
    })();


    overtime(1);
    overtime(2);
    overtime(3);
    overtime(4);
    overtime(); // 10

即对于前面的四个overtime函数被调用的时候,其实只是保存了变量而已,并没有求值,直到最后才一起求值,这样有利于提高效率。

 

 

 

 

 

 

 

 

https://rockjins.js.org/2017/02/15/2017-02-15-curring-uncurring/

posted @ 2017-04-24 23:42  Wayne-Zhu  阅读(544)  评论(0编辑  收藏  举报

一分耕耘,一分收获。