我在一些文章和博客中看到了curry函数的引用,但我找不到一个好的解释(或者至少一个有意义的解释!)


当前回答

在函数代数中,处理带有多个参数的函数(或相当于一个n元组的参数)有点不优雅——但是,正如Moses Schönfinkel(以及Haskell Curry)所证明的那样,这是不需要的:您所需要的只是带有一个参数的函数。

那么如何处理自然表示为f(x,y)的式子呢?好吧,你把它等价于f(x)(y)——f(x),叫它g,是一个函数,你把这个函数应用到y上。换句话说,你只有带一个参数的函数——但其中一些函数返回其他函数(也带一个参数;-)。

像往常一样,维基百科对此有一个很好的总结条目,有许多有用的指针(可能包括关于你最喜欢的语言的;-),以及稍微更严格的数学处理。

其他回答

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

它可以是一种用函数生成其他函数的方法。

在javascript中:

let add = function(x){
  return function(y){ 
   return x + y
  };
};

我们可以这样称呼它:

let addTen = add(10);

运行时,将10作为x传入;

let add = function(10){
  return function(y){
    return 10 + y 
  };
};

这意味着我们返回这个函数:

function(y) { return 10 + y };

所以当你打电话的时候

 addTen();

你真的在呼唤:

 function(y) { return 10 + y };

如果你这样做:

 addTen(4)

这就相当于:

function(4) { return 10 + 4} // 14

所以我们的addTen()总是给我们传入的任何东西加10。我们可以用同样的方法来构造类似的函数:

let addTwo = add(2)       // addTwo(); will add two to whatever you pass in
let addSeventy = add(70)  // ... and so on...

接下来的问题是,你到底为什么要这么做?它将一个急迫的操作x + y变成了一个可以轻松完成的操作,这意味着我们至少可以做两件事 1. 缓存昂贵的操作 2. 在功能范式中实现抽象。

想象我们的咖喱函数是这样的:

let doTheHardStuff = function(x) {
  let z = doSomethingComputationallyExpensive(x)
  return function (y){
    z + y
  }
}

我们可以调用这个函数一次,然后将结果传递给很多地方,这意味着我们只做一次计算上昂贵的事情:

let finishTheJob = doTheHardStuff(10)
finishTheJob(20)
finishTheJob(30)

我们可以用类似的方式得到抽象。

这里有一个具体的例子:

假设你有一个计算作用在物体上的引力的函数。如果你不知道公式,你可以在这里找到。这个函数接受三个必要的形参作为参数。

现在,在地球上,你只想计算这个星球上物体的力。在函数式语言中,你可以把地球的质量传递给函数,然后对它进行部分计算。你会得到另一个函数,它只接受两个参数,并计算地球上物体的引力。这叫做咖喱。

下面是Python中的一个小例子:

>>> from functools import partial as curry

>>> # Original function taking three parameters:
>>> def display_quote(who, subject, quote):
        print who, 'said regarding', subject + ':'
        print '"' + quote + '"'


>>> display_quote("hoohoo", "functional languages",
           "I like Erlang, not sure yet about Haskell.")
hoohoo said regarding functional languages:
"I like Erlang, not sure yet about Haskell."

>>> # Let's curry the function to get another that always quotes Alex...
>>> am_quote = curry(display_quote, "Alex Martelli")

>>> am_quote("currying", "As usual, wikipedia has a nice summary...")
Alex Martelli said regarding currying:
"As usual, wikipedia has a nice summary..."

(只是通过+来使用连接,以避免非python程序员分心。)

编辑添加:

看到http://docs.python.org/library/functools.html?highlight=partial functools.partial, 这也显示了Python实现的部分对象和函数的区别。

我发现这篇文章,以及它引用的文章,有助于更好地理解咖喱: http://blogs.msdn.com/wesdyer/archive/2007/01/29/currying-and-partial-function-application.aspx

正如其他人所提到的,它只是一种具有单参数函数的方法。

这很有用,因为你不需要假设有多少参数将被传入,所以你不需要2个参数,3个参数和4个参数函数。