我在一些文章和博客中看到了curry函数的引用,但我找不到一个好的解释(或者至少一个有意义的解释!)
当前回答
在函数代数中,处理带有多个参数的函数(或相当于一个n元组的参数)有点不优雅——但是,正如Moses Schönfinkel(以及Haskell Curry)所证明的那样,这是不需要的:您所需要的只是带有一个参数的函数。
那么如何处理自然表示为f(x,y)的式子呢?好吧,你把它等价于f(x)(y)——f(x),叫它g,是一个函数,你把这个函数应用到y上。换句话说,你只有带一个参数的函数——但其中一些函数返回其他函数(也带一个参数;-)。
像往常一样,维基百科对此有一个很好的总结条目,有许多有用的指针(可能包括关于你最喜欢的语言的;-),以及稍微更严格的数学处理。
其他回答
下面是泛型和最短版本的函数用n no curry的例子。的参数。
const add = a => b => b ? add(a + b) : a;
Const add = a => b => b ?Add (a + b): a; console.log(添加(1)(2)(3)(4)());
如果你理解了部分,你就成功了一半。partial的思想是将参数预先应用到一个函数,并返回一个只需要剩余参数的新函数。当这个新函数被调用时,它包括预加载的参数以及提供给它的任何参数。
在Clojure +中是一个函数,但要明确一点:
(defn add [a b] (+ a b))
您可能已经意识到inc函数只是简单地将1加到它传递的任何数字上。
(inc 7) # => 8
让我们自己使用partial来构建它:
(def inc (partial add 1))
Here we return another function that has 1 loaded into the first argument of add. As add takes two arguments the new inc function wants only the b argument -- not 2 arguments as before since 1 has already been partially applied. Thus partial is a tool from which to create new functions with default values presupplied. That is why in a functional language functions often order arguments from general to specific. This makes it easier to reuse such functions from which to construct other functions.
现在想象一下,如果语言足够聪明,能够自省地理解add需要两个参数。当我们向它传递一个参数时,如果函数部分应用了我们代表它传递的参数,并理解我们可能打算稍后提供另一个参数呢?然后,我们可以在不显式使用partial的情况下定义inc。
(def inc (add 1)) #partial is implied
这是一些语言的表现方式。当希望将函数组合成更大的转换时,它特别有用。这将把人们引向传感器。
“Currying”是一个获取多个参数的函数并将其转换为一系列函数的过程,每个函数接受一个参数并返回一个参数的函数,或者在最终函数的情况下,返回实际结果。
curry是将函数从可调用的f(a, b, c)转换为可调用的f(a)(b)(c)。
另外,curry是指将一个接受多个参数的函数分解为一系列接受部分参数的函数。
从字面上看,curry是函数的转换:从一种调用方式到另一种调用方式。在JavaScript中,我们通常创建一个包装器来保留原始函数。
curry不调用函数。它只是变换了它。
让我们创建一个curry函数,它对双实参函数执行curry。换句话说,对于双参数f(a, b)的curry(f)将其转换为f(a)(b)
function curry(f) { // curry(f) does the currying transform
return function(a) {
return function(b) {
return f(a, b);
};
};
}
// usage
function sum(a, b) {
return a + b;
}
let carriedSum = curry(sum);
alert( carriedSum(1)(2) ); // 3
如您所见,实现是一系列的包装器。
curry(func)的结果是一个包装器函数(a)。 当它像sum(1)一样被调用时,参数被保存在词法环境中,并返回一个新的包装器函数(b)。 然后sum(1)(2)最后调用函数(b)提供2,它将调用传递给原始的多参数sum。
curry函数应用于多个参数列表,而不仅仅是 一个。
这是一个常规的、非咖喱的函数,它加了两个Int 参数x和y:
scala> def plainOldSum(x: Int, y: Int) = x + y
plainOldSum: (x: Int,y: Int)Int
scala> plainOldSum(1, 2)
res4: Int = 3
这是一个类似的咖喱函数。而不是 对于一个包含两个Int形参的列表,您将此函数应用于两个包含一个Int形参的列表 Int参数each:
scala> def curriedSum(x: Int)(y: Int) = x + y
curriedSum: (x: Int)(y: Int)Intscala> second(2)
res6: Int = 3
scala> curriedSum(1)(2)
res5: Int = 3
这里发生的事情是,当您调用curriedSum时,实际上会得到两个背对背的传统函数调用。第一个函数 调用接受一个名为x的Int形参,并返回一个函数 为第二个函数。第二个函数接受Int形参 y。
这里有一个名为first的函数,它在精神上完成了第一个传统函数 函数调用curriedSum会做:
scala> def first(x: Int) = (y: Int) => x + y
first: (x: Int)(Int) => Int
对第一个函数应用1——换句话说,调用第一个函数 而传入1 -会得到第二个函数:
scala> val second = first(1)
second: (Int) => Int = <function1>
对第二个函数应用2得到的结果是:
scala> second(2)
res6: Int = 3