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


当前回答

Curry可以简化代码。这是使用它的主要原因之一。curry是将一个接受n个参数的函数转换为n个只接受一个参数的函数的过程。

其原理是传递传递函数的参数,使用closure(闭包)属性,将它们存储在另一个函数中并将其作为返回值,这些函数形成一个链,最后的参数被传递进来完成操作。

这样做的好处是可以通过一次处理一个参数来简化参数的处理,也可以提高程序的灵活性和可读性。这也使程序更易于管理。此外,将代码分割成更小的片段将使其易于重用。

例如:

function curryMinus(x) 
{
  return function(y) 
  {
    return x - y;
  }
}

var minus5 = curryMinus(1);
minus5(3);
minus5(5);

我还可以做…

var minus7 = curryMinus(7);
minus7(3);
minus7(5);

这对于使复杂的代码变得整洁和处理非同步方法等非常有用。

其他回答

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

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

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

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

curry的一个例子是当你有一个函数时,你现在只知道其中一个参数:

例如:

func aFunction(str: String) {
    let callback = callback(str) // signature now is `NSData -> ()`
    performAsyncRequest(callback)
}

func callback(str: String, data: NSData) {
    // Callback code
}

func performAsyncRequest(callback: NSData -> ()) {
    // Async code that will call callback with NSData as parameter
}

在这里,因为你不知道回调的第二个参数,当它发送给performAsyncRequest(_:)时,你必须创建另一个lambda /闭包来发送给函数。

curry是指将一个接受多个参数的函数分解为一系列函数,每个函数只接受一个参数。下面是JavaScript的一个例子:

function add (a, b) {
  return a + b;
}

add(3, 4); // returns 7

这是一个接受两个参数a和b的函数,并返回它们的和。现在我们将咖喱这个函数:

function add (a) {
  return function (b) {
    return a + b;
  }
}

这是一个接受一个参数a的函数,并返回一个接受另一个参数b的函数,该函数返回它们的和。

add(3)(4); // returns 7

var add3 = add(3); // returns a function

add3(4); // returns 7

第一个语句返回7,就像add(3,4)语句一样。 第二条语句定义了一个名为add3的新函数 给它的参数加上3。(这就是有些人所说的终结。) 第三条语句再次使用add3操作将3添加到4 结果是7。

在这里,您可以找到c#中curry实现的简单解释。在评论中,我试图展示咖喱是如何有用的:

public static class FuncExtensions {
    public static Func<T1, Func<T2, TResult>> Curry<T1, T2, TResult>(this Func<T1, T2, TResult> func)
    {
        return x1 => x2 => func(x1, x2);
    }
}

//Usage
var add = new Func<int, int, int>((x, y) => x + y).Curry();
var func = add(1);

//Obtaining the next parameter here, calling later the func with next parameter.
//Or you can prepare some base calculations at the previous step and then
//use the result of those calculations when calling the func multiple times 
//with different input parameters.

int result = func(1);