这里是计算矩形棱镜体积的一个例子。这是教科书咖喱。
function volume(l, w, h) {
return l * w * h;
}
function curriedVolume(length) {
return function(width) {
return function(height) {
return height * width * length;
}
}
}
volume(2, 3, 4); // 24
curriedVolume(2)(3)(4); // 24
这是一个类似的示例,除了非咖喱函数采用一个参数即对象。
function volume(dimensions) {
return dimensions.l * dimensions.w * dimensions.h;
}
function curriedVolume(dimension, finalDimensions={}) {
Object.assign(finalDimensions, dimension);
if (Object.keys(finalDimensions).length === 3) {
return finalDimensions.l * finalDimensions.w * finalDimensions.h;
}
return function(dimension) {
return curriedVolume(dimension, finalDimensions);
}
}
volume({
l: 2,
w: 3,
h: 4,
});
curriedVolume({ l: 2 })({ w: 3 })({ h: 4 }); // 24
curriedVolume({ w: 2, h: 3 })({ l: 4 }); // 24
这是否仍被视为“咖喱”?有效吗?
答案 0 :(得分:1)
我已经评论过,这个问题有点在意,但尽管感到有些顽皮,但我还是很感兴趣可以提供自己的观点。我还没有提供确切的答案(因为我不确定是否存在),但是我将通过调查断言您的第二个示例并不像该术语通常所说的那样混乱。
您的示例将部分应用参数,直到关闭了足够的参数以计算结果为止,随后将返回计算的体积。这不值得辩论。
要声称这是“ curry”的示例,您必须争论:
对于您的示例,这两个声明都必须是正确的,以符合currying的定义。
但是,现在您处于矛盾之中。通过1)对象参数不是“真正”的单数参数。但是然后在2)中,您必须直接与1)相矛盾,才能断言返回的函数只是一个参数的函数。因此存在这种不一致。
除了语义之外,传递单个对象作为参数会更改咖喱函数的调用机制,这样,如果您碰巧拥有三个伪参数(对象属性),则可以使用包含所有三个伪参数(对象属性)的对象进行调用。如果您不会获得返回的函数值,则可以立即获得计算出的体积。这使得函数不会轻易重入。想象一下,您正在将一些数据流的结果传递给该函数。现在,根据给定对象的状态,函数在完全相同的代码行中的行为有所不同。再次有争议的是,当涉及到curry时,这并没有遵循“法律精神”,因为您在函数中引入了副作用,使得很难推理代码的行为。最后,也许最重要的是,通过编写一个将对象作为参数接收的函数,您已经删除了函数的类型签名,以便在不读取内部代码本身的情况下也无法从中推断出任何内容。这将使其无法在元编程方法中使用,因为它将与期望具有两个或四个或十个属性的对象的函数共享相同的类型签名。
答案 1 :(得分:0)
是的,在函数中使用对象仍然很麻烦。
请参见this quote:
以Haskell Brooks Curry的名字命名的currying是将一个函数分解为一系列函数的过程,每个函数都有一个参数...
并且来自here:
Currying是一种将具有多个参数的函数评估为具有单个参数的函数序列的技术。
只要您的函数中没有两个参数,就可以,它仍然被认为是“ currying”。