我在一些文章和博客中看到了curry函数的引用,但我找不到一个好的解释(或者至少一个有意义的解释!)
当前回答
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 /闭包来发送给函数。
其他回答
在函数代数中,处理带有多个参数的函数(或相当于一个n元组的参数)有点不优雅——但是,正如Moses Schönfinkel(以及Haskell Curry)所证明的那样,这是不需要的:您所需要的只是带有一个参数的函数。
那么如何处理自然表示为f(x,y)的式子呢?好吧,你把它等价于f(x)(y)——f(x),叫它g,是一个函数,你把这个函数应用到y上。换句话说,你只有带一个参数的函数——但其中一些函数返回其他函数(也带一个参数;-)。
像往常一样,维基百科对此有一个很好的总结条目,有许多有用的指针(可能包括关于你最喜欢的语言的;-),以及稍微更严格的数学处理。
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);
这对于使复杂的代码变得整洁和处理非同步方法等非常有用。
下面是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实现的部分对象和函数的区别。
curry是一种可以应用于函数的转换,允许它们比以前少接受一个参数。
例如,在f#中你可以这样定义一个函数:-
let f x y z = x + y + z
这里函数f取参数x, y和z,并将它们相加:-
f 1 2 3
返回6。
根据我们的定义,我们可以定义f的curry函数:-
let curry f = fun x -> f x
其中'fun x - >fx '是一个lambda函数,在c#中等价于x => f(x)。此函数输入您希望curry的函数,并返回一个接受单个参数的函数,并返回指定的函数,其中第一个参数设置为输入参数。
使用前面的例子,我们可以得到f的curry值:-
let curryf = curry f
然后我们可以做以下的事情:-
let f1 = curryf 1
这为我们提供了一个函数f1,它等价于f1 y z = 1 + y + z。这意味着我们可以做以下事情
f1 2 3
返回6。
这个过程经常与“部分函数应用”相混淆,可以这样定义:-
let papply f x = f x
尽管我们可以将其扩展为多个参数,即:-
let papply2 f x y = f x y
let papply3 f x y z = f x y z
etc.
部分应用程序将接受函数和形参并返回一个需要一个或多个更少形参的函数,正如前面两个示例所示,它直接在标准f#函数定义中实现,因此我们可以通过以下方式实现前面的结果
let f1 = f 1
f1 2 3
它将返回一个6的结果。
结论:-
咖喱和部分函数应用的区别是:-
curry接受一个函数,并提供一个接受单个参数的新函数,并返回指定函数,并将其第一个参数设置为该参数。这允许我们将具有多个形参的函数表示为一系列单实参函数。例子:-
let f x y z = x + y + z
let curryf = curry f
let f1 = curryf 1
let f2 = curryf 2
f1 2 3
6
f2 1 3
6
偏函数应用更直接——它接受一个函数和一个或多个参数,并返回一个函数,其中前n个参数设置为指定的n个参数。例子:-
let f x y z = x + y + z
let f1 = f 1
let f2 = f 2
f1 2 3
6
f2 1 3
6
curry是Java Script的高阶函数之一。
curry是一个包含许多参数的函数,它会被重写,这样它会接受第一个参数并返回一个函数,而这个函数会使用剩余的参数并返回值。
困惑吗?
让我们看一个例子,
function add(a,b)
{
return a+b;
}
add(5,6);
这类似于下面的咖喱函数,
function add(a)
{
return function(b){
return a+b;
}
}
var curryAdd = add(5);
curryAdd(6);
那么这个代码是什么意思呢?
现在再读一遍定义,
curry是一个包含许多参数的函数,它被重写为接受第一个参数并返回一个函数,该函数反过来使用剩余的参数并返回值。
不过,困惑吗? 让我来详细解释一下!
当你调用这个函数时,
var curryAdd = add(5);
它会返回一个这样的函数,
curryAdd=function(y){return 5+y;}
这叫做高阶函数。也就是说,依次调用一个函数返回另一个函数是高阶函数的精确定义。这是图例的最大优势,Java Script。 回到咖喱,
这一行将把第二个参数传递给curryAdd函数。
curryAdd(6);
结果是,
curryAdd=function(6){return 5+6;}
// Which results in 11
希望你能理解这里咖喱的用法。 那么,说到优点,
为什么鞭笞?
它利用了代码可重用性。 代码越少,错误越少。 你可能会问它是怎么少代码的?
我可以证明它与ECMA脚本6新的特征箭头功能。
是的!ECMA 6,为我们提供了美妙的功能,叫做箭头函数,
function add(a)
{
return function(b){
return a+b;
}
}
借助箭头函数,我们可以将上面的函数写成如下形式:
x=>y=>x+y
酷吧?
所以,更少的代码和更少的错误!!
在这些高阶函数的帮助下,可以很容易地开发出无bug的代码。
我向你挑战!
霍普,你知道什么是咖喱。如果你有任何需要澄清的地方,请在这里评论。
谢谢,祝您愉快!
推荐文章
- 如何使用Jest测试对象键和值是否相等?
- 将长模板文字行换行为多行,而无需在字符串中创建新行
- 如何在JavaScript中映射/减少/过滤一个集?
- Bower: ENOGIT Git未安装或不在PATH中
- 添加javascript选项选择
- 在Node.js中克隆对象
- 为什么在JavaScript的Date构造函数中month参数的范围从0到11 ?
- 使用JavaScript更改URL参数并指定默认值
- 在window.setTimeout()发生之前取消/终止
- 如何删除未定义和空值从一个对象使用lodash?
- 检测当用户滚动到底部的div与jQuery
- 在JavaScript中检查字符串包含另一个子字符串的最快方法?
- 检测视口方向,如果方向是纵向显示警告消息通知用户的指示
- ASP。NET MVC 3 Razor:在head标签中包含JavaScript文件
- 禁用从HTML页面中拖动图像