阅读维基百科关于First-Class函数的文章,有一个很好的语言支持表,用于函数式编程的各个方面:http://en.wikipedia.org/wiki/First-class_function#Language_support
JavaScript列为没有部分功能应用程序。但是,有一些技术可用于创建一个函数,该函数返回一个函数,该函数包含一些存储在闭包中的参数,即:
var add = function(a, b){
return a + b;
},
apply = function(fn, a){
return function(b){
return fn(a, b);
}
},
addFive = apply(add, 5);
console.log(addFive(2)); // prints 7
这不是部分功能应用吗?如果没有,有人可以提供另一种语言的部分功能应用示例并解释它是如何不同的吗?
谢谢!
答案 0 :(得分:6)
你应该注意理解这个概念叫做currying(在Haskell B. Curry之后)。在n + 1个参数的函数和一个参数的函数之间存在同构,其中一个参数返回具有n个参数的函数。如果你以递归方式应用它,你可以编写任意数量参数的函数作为函数的函数。
这就是为什么函数式语言中的函数通常被输入为X -> Y -> Z
的含义,这是一个函数,它接受X
并返回一个函数,Y
返回Z
}。此签名还意味着您只需提供X
,该函数将自动返回一个函数。
在Javascript中,两个参数的函数将具有签名X * Y -> Z
,这意味着它是一个带有X * Y
对并返回Z
的函数。但是你不能提供半对。
有两种方法:
始终手动调整您的功能。您的add
函数可以写成:
var curryadd = function(a){
return function(b){ return a + b; }
};
有了这个,你现在有了一个函数,它具有部分函数应用所需的实际signatur Int -> Int -> Int
。但是,您还必须确保将此函数称为curryadd(5)(10)
,这是不自然的。
提供更高阶的功能,这可以解决您的功能问题。在你的情况下,apply会做两件事,它会影响你的add函数并绑定参数。这可以分为两部分:
var curry = function(fn) {
return function(a){ return function(b){ return fn(a,b); } }
};
这实际上将实现具有对作为参数的函数和返回函数的函数之间的同构。还有一种方法可以写uncurry
向后做同样的事情。
因为你必须手动完成所有这些并且没有直接的语言支持,所以javascript被认为没有部分功能应用程序(这并不表示你不能将它添加到语言中)。
答案 1 :(得分:5)
您展示的是高阶函数的示例,函数将函数作为参数和/或返回函数。
部分申请是不同的。 Here a Haskell example:
add :: Int -> Int -> Int
add x y = x + y
addOne = add 1
add
是一个函数,需要两个Int
并返回一个Int
,表示为Int -> Int -> Int
。如果您不熟悉语法,在Javascript中大致如下所示:
/**
* @param int x
* @param int y
* @return int
*/
function add(x, y) {
return x + y;
}
add 1
仅使用一个参数调用此函数,该参数返回一个新函数,该函数需要一个Int
并返回Int
(Int -> Int
)。 add
函数未明确设计为高阶函数,只是部分应用。
答案 2 :(得分:5)
var func1 = function(a, b) {
return a + b;
}
var func2 = func1.bind(undefined, 3);
func2(1); // 4
func2(2); // 5
func2(3); // 6
答案 3 :(得分:1)
如其他答案中所述,你所描述的是cur ;;正如你所认识到的那样,这是一种部分应用。
但是,如果您想要的只是部分应用程序,则可以使用underscore.js,这会添加许多函数式编程实用程序:http://documentcloud.github.com/underscore/