我在一些文章和博客中看到了curry函数的引用,但我找不到一个好的解释(或者至少一个有意义的解释!)
当前回答
下面是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实现的部分对象和函数的区别。
其他回答
下面是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实现的部分对象和函数的区别。
正如所有其他答案一样,咖喱有助于创建部分应用函数。Javascript不提供自动咖喱的原生支持。因此,上面提供的示例可能对实际编码没有帮助。在livescript中有一些很好的例子(基本上编译成js) http://livescript.net/
times = (x, y) --> x * y
times 2, 3 #=> 6 (normal use works as expected)
double = times 2
double 5 #=> 10
在上面的例子中,当你给出较少的no of参数时,livescript会为你生成新的curried函数(double)
如果你理解了部分,你就成功了一半。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
这是一些语言的表现方式。当希望将函数组合成更大的转换时,它特别有用。这将把人们引向传感器。
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。
它可以是一种用函数生成其他函数的方法。
在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)
我们可以用类似的方式得到抽象。
推荐文章
- 一元加/数字(x)和parseFloat(x)之间的区别是什么?
- angularjs中的compile函数和link函数有什么区别
- 删除绑定中添加的事件监听器
- 很好的初学者教程socket.io?
- HtmlSpecialChars在JavaScript中等价于什么?
- React: 'Redirect'没有从' React -router-dom'中导出
- 如何在React中使用钩子强制组件重新渲染?
- 我如何使用Jest模拟JavaScript的“窗口”对象?
- 我如何等待一个承诺完成之前返回一个函数的变量?
- 在JavaScript中根据键值查找和删除数组中的对象
- 使嵌套JavaScript对象平放/不平放的最快方法
- 如何以及为什么'a'['toUpperCase']()在JavaScript工作?
- 有Grunt生成index.html不同的设置
- 文档之间的区别。addEventListener和window。addEventListener?
- 如何检查动态附加的事件监听器是否存在?