Underscore.js功能性编程是假的吗?

aku*_*kuz 2 javascript functional-programming underscore.js

根据我对函数式编程的理解,你应该能够链接多个函数,然后通过输入一次数据来执行整个链.

换句话说,当我执行以下操作(伪代码)时:

list = [1, 2, 3];
sum_squares = list
   .map(function(item) { return item * item; })
   .reduce(function(total, item) { return total + item; }, 0);
Run Code Online (Sandbox Code Playgroud)

我希望列表将被遍历一次,当每个值都被平方,然后一切都将被加起来(因此,reduce操作将根据需要调用map操作).

但是,当我查看Underscore.js的源代码时,我发现所有"函数式编程"函数实际上都会生成中间集合,例如:

// Return the results of applying the iteratee to each element.
_.map = _.collect = function(obj, iteratee, context) {
  iteratee = cb(iteratee, context);
  var keys = !isArrayLike(obj) && _.keys(obj),
      length = (keys || obj).length,
      results = Array(length);
  for (var index = 0; index < length; index++) {
    var currentKey = keys ? keys[index] : index;
    results[index] = iteratee(obj[currentKey], currentKey, obj);
  }
  return results;
};
Run Code Online (Sandbox Code Playgroud)

所以问题是,如标题所述,我们在使用Underscore.js时自欺欺人地进行函数式编程?

我们实际上做的是使程序看起来像函数式编程,而实际上它实际上并不是函数式编程.想象一下,我在长度为N的列表上构建了一长串K filter()函数,然后在Underscore.js中,我的计算复杂度将是O(K*N)而不是函数编程中预期的O(N).

PS我在JavaScript中听到了很多关于函数式编程的知识,我期待看到一些函数,生成器,绑定......我错过了什么?

Ber*_*rgi 5

Underscore.js功能性编程是假的吗?

不,Underscore确实有很多有用的功能辅助功能.但是,是的,他们做错了.你可能想要看一下Ramda.

我希望列表将被遍历一次

是的,list只会被遍历一次.它不会被改变,它不会被保存在内存中(如果你没有变量引用它).什么reduce穿越是一个不同的列表,所生产的一个map.

所有功能实际上都产生了中间集合

是的,这是用JavaScript这样的语言实现这一点的最简单方法.许多人在map调用之前依赖于执行所有回调reduce,因为它们使用副作用.JS不强制执行纯函数,库作者不想让人混淆.

请注意,即使在像Haskell这样的纯语言中,也会构建一个中间结构1,尽管它会被懒散地使用,因此它永远不会被分配为一个整体.

有些库可以用严格的语言实现这种优化,其中传感器的概念可以从Clojure中获知.JS中的例子是换能器,换能器-js,换能器.js腋下.下划线和Ramda一直在寻找到他们2了.

我期待看到一些发电机

是的,可以懒散地消耗的生成器/迭代器是另一种选择.你想看看Lazy.js,highlandimmutable-js.

[1]:嗯,不是真的 - 这是一个太容易的优化
[2]:https://github.com/jashkenas/underscore/issues/1896,https://github.com/ramda/ramda/pull/865