這個問題讓我頗感興趣。這是我的一些想法。
感覺就像在'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