我经常在网上看到各种各样的抱怨,说其他人的套用例子并不是套用,而实际上只是部分应用。
我还没有找到一个像样的解释来解释什么是部分应用,或者它与咖喱有什么不同。这似乎是一种普遍的混淆,类似的例子在一些地方被描述为套用,在另一些地方被描述为部分应用。
谁能给我提供这两个术语的定义,以及它们之间的区别?
我经常在网上看到各种各样的抱怨,说其他人的套用例子并不是套用,而实际上只是部分应用。
我还没有找到一个像样的解释来解释什么是部分应用,或者它与咖喱有什么不同。这似乎是一种普遍的混淆,类似的例子在一些地方被描述为套用,在另一些地方被描述为部分应用。
谁能给我提供这两个术语的定义,以及它们之间的区别?
当前回答
这里的很多人都没有正确地解决这个问题,也没有人谈论过重叠。
简单的答案
curry:让你调用一个函数,把它分成多个调用,每次调用提供一个参数。
部分应用:允许你调用一个函数,把它分成多个调用,每次调用提供多个参数。
两者之间的重要区别之一是调用 部分应用的函数立即返回结果,而不是另一个 沿着咖喱链;这种区别可以用例子来说明 显然,对于集度大于2的函数。
这是什么意思?这意味着对一个局部函数最多有两次调用。curry的参数和参数的数量一样多。如果curry函数只有两个参数,那么它本质上与偏函数相同。
例子
部分应用和咖喱
function bothPartialAndCurry(firstArgument) {
return function(secondArgument) {
return firstArgument + secondArgument;
}
}
const partialAndCurry = bothPartialAndCurry(1);
const result = partialAndCurry(2);
部分应用程序
function partialOnly(firstArgument, secondArgument) {
return function(thirdArgument, fourthArgument, fifthArgument) {
return firstArgument + secondArgument + thirdArgument + fourthArgument + fifthArgument;
}
}
const partial = partialOnly(1, 2);
const result = partial(3, 4, 5);
局部套用
function curryOnly(firstArgument) {
return function(secondArgument) {
return function(thirdArgument) {
return function(fourthArgument ) {
return function(fifthArgument) {
return firstArgument + secondArgument + thirdArgument + fourthArgument + fifthArgument;
}
}
}
}
}
const curryFirst = curryOnly(1);
const currySecond = curryFirst(2);
const curryThird = currySecond(3);
const curryFourth = curryThird(4);
const result = curryFourth(5);
// or...
const result = curryOnly(1)(2)(3)(4)(5);
命名约定
等我有时间再写,很快就有时间了。
其他回答
局部套用
维基百科上说
curry是一种将带有多个参数的函数转换为带有单个参数的函数序列的技术。
例子
const add = (a, b) => a + b
const addC = (a) => (b) => a + b // curried function. Where C means curried
部分应用程序
文章刚刚好FP:部分应用
部分应用是将部分(而不是全部)参数应用到函数,并返回一个新函数等待其余参数。这些应用的参数存储在闭包中,并且将来对任何部分应用的返回函数仍然可用。
例子
const add = (a) => (b) => a + b
const add3 = add(3) // add3 is a partially applied function
add3(5) // 8
区别在于
咖喱是一种技术(模式) Partial application是一个带有一些预定义参数的函数(如前面示例中的add3)
这里的很多人都没有正确地解决这个问题,也没有人谈论过重叠。
简单的答案
curry:让你调用一个函数,把它分成多个调用,每次调用提供一个参数。
部分应用:允许你调用一个函数,把它分成多个调用,每次调用提供多个参数。
两者之间的重要区别之一是调用 部分应用的函数立即返回结果,而不是另一个 沿着咖喱链;这种区别可以用例子来说明 显然,对于集度大于2的函数。
这是什么意思?这意味着对一个局部函数最多有两次调用。curry的参数和参数的数量一样多。如果curry函数只有两个参数,那么它本质上与偏函数相同。
例子
部分应用和咖喱
function bothPartialAndCurry(firstArgument) {
return function(secondArgument) {
return firstArgument + secondArgument;
}
}
const partialAndCurry = bothPartialAndCurry(1);
const result = partialAndCurry(2);
部分应用程序
function partialOnly(firstArgument, secondArgument) {
return function(thirdArgument, fourthArgument, fifthArgument) {
return firstArgument + secondArgument + thirdArgument + fourthArgument + fifthArgument;
}
}
const partial = partialOnly(1, 2);
const result = partial(3, 4, 5);
局部套用
function curryOnly(firstArgument) {
return function(secondArgument) {
return function(thirdArgument) {
return function(fourthArgument ) {
return function(fifthArgument) {
return firstArgument + secondArgument + thirdArgument + fourthArgument + fifthArgument;
}
}
}
}
}
const curryFirst = curryOnly(1);
const currySecond = curryFirst(2);
const curryThird = currySecond(3);
const curryFourth = curryThird(4);
const result = curryFourth(5);
// or...
const result = curryOnly(1)(2)(3)(4)(5);
命名约定
等我有时间再写,很快就有时间了。
在学习的过程中,我经常有这个问题,后来也被问过很多次。我能描述的最简单的方式是两者都是一样的:)让我解释一下…有明显的区别。
部分应用程序和curry都涉及向函数提供参数,可能不是一次全部提供。一个相当典型的例子是两个数字相加。在伪代码(实际上是没有关键字的JS)中,基函数可能如下所示:
add = (x, y) => x + y
如果我想要一个“addOne”函数,我可以部分应用它或curry它:
addOneC = curry(add, 1)
addOneP = partial(add, 1)
现在使用它们是很清楚的:
addOneC(2) #=> 3
addOneP(2) #=> 3
那么有什么不同呢?好吧,这很微妙,但部分应用程序涉及提供一些参数,然后返回的函数将在下次调用时执行主函数,而curry将一直等待,直到它拥有所有必要的参数:
curriedAdd = curry(add) # notice, no args are provided
addOne = curriedAdd(1) # returns a function that can be used to provide the last argument
addOne(2) #=> returns 3, as we want
partialAdd = partial(add) # no args provided, but this still returns a function
addOne = partialAdd(1) # oops! can only use a partially applied function once, so now we're trying to add one to an undefined value (no second argument), and we get an error
简而言之,使用partial application预填充一些值,知道下次调用该方法时,它将执行,所有未提供的参数都未定义;当您希望连续多次返回部分应用的函数以实现函数签名时,请使用curry。最后一个人为的例子:
curriedAdd = curry(add)
curriedAdd()()()()()(1)(2) # ugly and dumb, but it works
partialAdd = partial(add)
partialAdd()()()()()(1)(2) # second invocation of those 7 calls fires it off with undefined parameters
希望这能有所帮助!
更新:一些语言或库实现将允许您传递一个arity(最终计算中的参数总数)到部分应用程序实现,这可能会将我的两个描述合并成令人困惑的混乱…但在这一点上,这两种技术在很大程度上是可以互换的。
注意:本文摘自f# Basics,这是一篇非常好的介绍性文章,供。net开发人员学习函数式编程。
Currying means breaking a function with many arguments into a series of functions that each take one argument and ultimately produce the same result as the original function. Currying is probably the most challenging topic for developers new to functional programming, particularly because it is often confused with partial application. You can see both at work in this example: let multiply x y = x * y let double = multiply 2 let ten = double 5 Right away, you should see behavior that is different from most imperative languages. The second statement creates a new function called double by passing one argument to a function that takes two. The result is a function that accepts one int argument and yields the same output as if you had called multiply with x equal to 2 and y equal to that argument. In terms of behavior, it’s the same as this code: let double2 z = multiply 2 z Often, people mistakenly say that multiply is curried to form double. But this is only somewhat true. The multiply function is curried, but that happens when it is defined because functions in F# are curried by default. When the double function is created, it’s more accurate to say that the multiply function is partially applied. The multiply function is really a series of two functions. The first function takes one int argument and returns another function, effectively binding x to a specific value. This function also accepts an int argument that you can think of as the value to bind to y. After calling this second function, x and y are both bound, so the result is the product of x and y as defined in the body of double. To create double, the first function in the chain of multiply functions is evaluated to partially apply multiply. The resulting function is given the name double. When double is evaluated, it uses its argument along with the partially applied value to create the result.
有趣的问题。经过一番搜索,“部分函数应用程序不是咖喱”给出了我找到的最好的解释。我不能说实际的区别对我来说特别明显,但我不是一个FP专家……
另一个看起来很有用的页面(我承认我还没有完全读完)是“用Java闭包curry和Partial Application”。
注意,这看起来确实是一对被广泛混淆的术语。