我不认为我已经讨好了.我理解它的作用,以及如何做到这一点.我想不出我会用它的情况.
你在JavaScript中使用currying(或者使用它的主要库在哪里)?欢迎DOM操作或一般应用程序开发示例.
其中一个答案提到了动画.函数如slideUp
,fadeIn
将元素作为参数,通常是一个curried函数,返回高阶函数,内置默认的"动画函数".为什么这比仅使用某些默认值更高的函数更好?
使用它有什么缺点吗?
根据要求,这里有一些关于JavaScript currying的好资源:
http://www.dustindiaz.com/javascript-curry/
Crockford,Douglas(2008)JavaScript:The Good Parts
http://www.svendtofte.com/code/curried_javascript/ (绕道进入ML所以跳过"ML中的速成课程"中的整个部分,然后重新开始"如何编写咖喱JavaScript")
http://web.archive.org/web/20111217011630/http://blog.morrisjohns.com:80/javascript_closures_for_dummies
JavaScript闭包如何工作?
http://ejohn.org/blog/partial-functions-in-javascript(Resig先生关于钱的照常)
http://benalman.com/news/2010/09/partial-application-in-javascript/
我会在评论中添加更多内容.
因此,根据答案,currying和部分应用一般是便利技术.
如果您经常通过使用相同配置调用高级函数来"精炼"高级函数,则可以使用更高级别的函数来设置(或使用Resig的部分)来创建简单,简洁的帮助器方法.
以下是使用闭包的JavaScript中currying的一个有趣且实用的用法:
function converter(toUnit, factor, offset, input) { offset = offset || 0; return [((offset + input) * factor).toFixed(2), toUnit].join(" "); } var milesToKm = converter.curry('km', 1.60936, undefined); var poundsToKg = converter.curry('kg', 0.45460, undefined); var farenheitToCelsius = converter.curry('degrees C', 0.5556, -32); milesToKm(10); // returns "16.09 km" poundsToKg(2.5); // returns "1.14 kg" farenheitToCelsius(98); // returns "36.67 degrees C"
这依赖于curry
扩展Function
,虽然你可以看到它只使用apply
(没什么太花哨):
Function.prototype.curry = function() { if (arguments.length < 1) { return this; //nothing to curry with - return function } var __method = this; var args = toArray(arguments); return function() { return __method.apply(this, args.concat([].slice.apply(null, arguments))); } }
@Hank Gay
回应EmbiggensTheMind的评论:
我想不出一个实例,其中curry -by本身 - 在JavaScript中很有用; 它是一种将具有多个参数的函数调用转换为函数调用链的技术,每个调用都有一个参数,但JavaScript在单个函数调用中支持多个参数.
在JavaScript中 - 我假设大多数其他实际语言(不是lambda演算) - 它通常与部分应用程序相关联.John Resig 更好地解释了它,但要点是有一些逻辑将应用于两个或多个参数,并且您只知道其中一些参数的值.
您可以使用部分应用程序/ currying来修复这些已知值并返回仅接受未知数的函数,以便在您实际拥有要传递的值时调用.这提供了一种很好的方法来避免重复自己,当你一直使用所有相同的值而一次调用相同的JavaScript内置函数时.窃取约翰的例子:
String.prototype.csv = String.prototype.split.partial(/,\s*/); var results = "John, Resig, Boston".csv(); alert( (results[1] == "Resig") + " The text values were split properly" );
我发现类似python的函数functools.partial
在JavaScript中更有用:
function partial(fn) { return partialWithScope.apply(this, Array.prototype.concat.apply([fn, this], Array.prototype.slice.call(arguments, 1))); } function partialWithScope(fn, scope) { var args = Array.prototype.slice.call(arguments, 2); return function() { return fn.apply(scope, Array.prototype.concat.apply(args, arguments)); }; }
你为什么要用它?要使用此this
功能的常见情况是,您希望将函数绑定到值:
var callback = partialWithScope(Object.function, obj);
现在,当调用回调时,this
指向obj
.这在事件情况下很有用,或者节省一些空间,因为它通常会缩短代码.
Currying类似于partial,不同之处在于currying返回的函数只接受一个参数(据我所知).
同意Hank Gay - 它在某些真正的函数式编程语言中非常有用 - 因为它是必要的部分.例如,在Haskell中,您根本无法将多个参数带到函数中 - 您无法在纯函数式编程中执行此操作.你一次拿一个参数并建立你的功能.在JavaScript中,尽管有像"转换器"这样的人为例子,但它根本就没有必要.这是相同的转换器代码,无需curry:
var converter = function(ratio, symbol, input) { return (input*ratio).toFixed(2) + " " + symbol; } var kilosToPoundsRatio = 2.2; var litersToUKPintsRatio = 1.75; var litersToUSPintsRatio = 1.98; var milesToKilometersRatio = 1.62; converter(kilosToPoundsRatio, "lbs", 4); //8.80 lbs converter(litersToUKPintsRatio, "imperial pints", 2.4); //4.20 imperial pints converter(litersToUSPintsRatio, "US pints", 2.4); //4.75 US pints converter(milesToKilometersRatio, "km", 34); //55.08 km
我非常希望Douglas Crockford在"JavaScript:The Good Parts"中提到过currying的历史和实际使用,而不是他的不和之言.在读完之后的最长时间里,我感到很困惑,直到我学习功能编程并意识到它来自哪里.
经过一番思考之后,我认为在JavaScript中有一个有效的用例:如果你试图使用JavaScript编写纯函数式编程技术.看起来像一个罕见的用例.