Groovy的实现curry
实际上在任何时候都不会咖喱,甚至是在幕后。它本质上与部分应用程序相同。
的curry
,rcurry
并且ncurry
方法返回一个CurriedClosure
对象持有的绑定参数。它也有一个方法getUncurriedArguments
(名称不正确-您是咖喱函数,而不是参数),该方法返回传递给它的带有绑定参数的参数组成。
当关闭被调用,它最终调用的invokeMethod
方法MetaClassImpl
,看看其中明确检查调用对象的实例CurriedClosure
。如果是这样,它将使用上述内容getUncurriedArguments
构成要应用的完整参数数组:
if (objectClass == CurriedClosure.class) {
// ...
final Object[] curriedArguments = cc.getUncurriedArguments(arguments);
// [Ed: Yes, you read that right, curried = uncurried. :) ]
// ...
return ownerMetaClass.invokeMethod(owner, methodName, curriedArguments);
}
基于上述令人困惑且有些不一致的术语,我怀疑撰写此文章的人对概念有很好的理解,但也许有些着急,并且像许多聪明的人一样,将部分应用程序与匆忙混为一谈。如果有些不幸,这是可以理解的(请参阅保罗·金的答案)。在不破坏向后兼容性的情况下很难纠正此问题。
我建议的一种解决方案是重载该curry
方法,以便在不传递任何参数的情况下进行真正的计算,并反对使用支持新partial
功能的参数来调用该方法。这似乎有些奇怪,但是它将最大程度地实现向后兼容性(因为没有理由使用带有零参数的部分应用程序),同时避免了(IMHO)更为丑陋的情况,即使用新的名称不同的函数进行适当的计算,而该函数实际上named curry
所做的事情与众不同且令人困惑。
curry
毋庸置疑,通话结果与实际交易完全不同。如果确实使用了该函数,则可以编写:
def add = { x, y -> x + y }
def addCurried = add.curry() // should work like { x -> { y -> x + y } }
def add1 = addCurried(1) // should work like { y -> 1 + y }
assert add1(1) == 2
…它会起作用,因为addCurried
应该像那样起作用{ x -> { y -> x + y } }
。相反,它引发了运行时异常,并且您在内部死了一些。