2012-03-22 65 views
8

通过一流的功能,维基百科的文章阅读,还有的函数式编程的各个方面的语言支持一个不错的表:http://en.wikipedia.org/wiki/First-class_function#Language_supportJavaScript是否支持部分功能应用?

的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 

这难道不是局部的功能应用?如果不是,有人可以提供另一种语言的部分功能应用程序的例子,并解释它是如何不同?

谢谢!

回答

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并返回一个IntInt -> Int) 。 add函数没有明确地设计成更高阶的函数,它只是部分应用。

+0

原谅我,我不是熟悉Haskell语法。 “add”的函数签名是否说“add”需要两个Ints并返回一个Int?这是说,调用一个只有1个参数的函数会隐式地返回部分应用的函数吗? – 2012-03-22 07:19:41

+0

翻译成Javascript。是的,简单来说,'Int - > Int - > Int'表示它需要两个'Int'并返回一个。也许更正确,但它会将一个“Int”和另一个“Int”转换为另一个“Int”。我猜想,真正的哈斯克勒仍然会遇到我的术语问题,但是对于外行来说,这应该是可以做到的。 :o) – deceze 2012-03-22 07:23:22

+1

我想是这样的 - 即'add'就像这样:http://paste.pocoo.org/show/569340/ – ThiefMaster 2012-03-22 07:23:50

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; } 
    }; 
    

有了这个,你现在拥有的实际签字:Int -> Int -> Int这是需要部分功能的应用程序的功能。但是,您还必须确保将此功能称为curryadd(5)(10),这是不自然的。

  • 提供更高阶的功能,可以让您的功能更加完美。在你的情况下,应用程序做两件事情,它curries你的add函数并绑定参数。这两个部分可分为:

    var curry = function(fn) { 
        return function(a){ return function(b){ return fn(a,b); } } 
    }; 
    

这实际上将实现功能之间的同构与对作为参数和返回函数的函数。还有一种方法可以编写uncurry,它可以向后做同样的事情。

因为你必须手动完成所有这些操作,并且没有直接的语言支持,所以说javascript没有部分功能应用程序(并不是说你不能将它添加到语言中)。

+0

我想你在内部函数中忘记了一些'return'语句。 – ThiefMaster 2012-03-22 07:39:25

+0

@ThiefMaster:是的,我后来注意到,但没有互联网连接来改变它。我猜你有时候会忘记它们,如果你习惯了很多功能性语言,而不需要它们。 – LiKao 2012-03-22 15:18:30

1

正如在其他答案中指出的那样,你描述的是currying;如您所识别,它是一种部分应用的形式。

但是,如果你想要的只是部分应用程序,你可以使用underscore.js,它增加了很多功能的编程工具:http://documentcloud.github.com/underscore/

+0

感谢您的额外答复。在我的JavaScript编程中,我使用了下划线和相当多的函数式编程技巧。我只是想在维基百科文章中澄清“部分功能应用”的含义。我现在看到,这是一个本地语言支持问题,而不是通过高阶函数来实现它。 – 2012-03-22 18:53:51

3
var func1 = function(a, b) { 
    return a + b; 
} 

var func2 = func1.bind(undefined, 3); 

func2(1); // 4 
func2(2); // 5 
func2(3); // 6 

检查docs at developer.mozilla.org

+1

这似乎是最直接的答案,因为'绑定'现在是语言的原生语言。 – 2014-02-08 18:15:38

相关问题