2012-03-22 43 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

相關問題