这个问题让我颇感兴趣。这是我的一些想法。
感觉就像在'chain()模式中使用underscore.js'脱离了函数式编程范例。基本上,不是在函数上调用函数,而是以OOP方式调用包装对象实例的方法。
我自己在这里和那里使用underscore's chain(),但这个问题让我想到了。如果最好简单地创建更有意义的函数,然后可以按顺序调用,而不必使用chain()。然后,您的例子是这个样子:
arr = [1,2,3]
double = (arr) -> _.map(arr, (el) -> 2 * el)
sum = (arr) -> _.reduce(arr, (s, n) -> s + n)
out = (r) -> 10 * r
result = out sum double arr
# probably a less ambiguous way to do it would be
result = out(sum(double arr))
在真正的函数式编程语言展望(如..不是JavaScript更多功能),似乎你可以做完全有同样的事情在一个更简单的方式。这是用标准ML编写的相同程序。请注意,只有一个参数调用map会返回另一个函数。没有必要像在JavaScript中那样将这个映射封装在另一个函数中。
val arr = [1,2,3];
val double = map (fn x => 2*x);
val sum = foldl (fn (a,b) => a+b) 0;
val out = fn r => 10*r;
val result = out(sum(double arr))
标准ML还允许您创建运营商,这意味着我们可以作出这样可以用来调用这些函数以更直观的顺序有点“链”操作。
infix 1 |>;
fun x |> f = f x;
val result = arr |> double |> sum |> out
我也觉得这underscore.js链具有类似于函数式编程单子的东西,但我不知道很多关于这些。尽管如此,我感觉这种数据处理流水线并不是您通常使用monads来处理的东西。
我希望具有更多功能编程经验的人可以切入并纠正我,如果我在上面的任何一点上都错了。
UPDATE
略有下车的话题,但一个的方式创造的部分功能可能是以下几点:
// extend underscore with partialr function
_.mixin({
partialr: function (fn, context) {
var args = Array.prototype.slice.call(arguments, 2);
return function() {
return fn.apply(context, Array.prototype.slice.call(arguments).concat(args));
};
}
});
此功能现在可以用于从任何下划线函数创建一个部分功能,因为他们大多数将输入数据作为第一个参数。例如,SUM函数现在可以像
var sum = _.partialr(_.reduce, this, function (s, n) { return s + n; });
sum([1,2,3]);
我还是喜欢创建ARR |>双|>和|>出过了(SUM(双(ARR)))虽然。 Underscore的链()很好,因为它读取更自然的顺序。
您是否看到此线程https://github.com/documentcloud/underscore/pull/499?如果你有一个很好的现实世界的例子,你可以试着问Jeremy为什么他这个拉请求是不合适的。 – Karolis 2012-03-28 21:52:38
什么是' - >'语法? – Marcin 2012-04-23 17:40:27
Hi @Marcin,道歉,那就是CoffeeScript。 '(r) - > 10 * r'与'function(r){return 10 * r; }' – latentflip 2012-04-24 09:15:31