## Currying
我遇見的大多數碼農都讀過“[四人幫](http://baike.baidu.com/view/66964.htm#2)”的那本《設計模式》。任何稍有自尊心的碼農都會說這本書和語言無關,因此無論你用什么編程語言,當中提到的那些模式大體上適用于所有軟件工程。聽起來很厲害,然而事實卻不是這樣。
函數式語言的表達能力很強。用這種語言編程的時候基本不需要設計模式,因為這種語言層次已經足夠高,使得使用者可以以概念編程,從而完全不需要設計模式了。以[適配器模式](http://zh.wikipedia.org/wiki/%E9%80%82%E9%85%8D%E5%99%A8%E6%A8%A1%E5%BC%8F)為例(有人知道這個模式和[外觀模式](http://zh.wikipedia.org/wiki/%E9%80%82%E9%85%8D%E5%99%A8%E6%A8%A1%E5%BC%8F)有什么區別嗎?怎么覺得有人為了出版合同的要求而硬生生湊頁數?)(譯者:您不愧是高級黑啊)。對于一個支持currying技術的語言來說,這個模式就是多余的。
在Jaya中最有名的適配器模式就是在其“默認”抽象單元中的應用:類。在函數式語言中這種模式其實就是函數。在這個模式中,一個接口被轉換成另外一個接口,讓不同的用戶代碼調用。接下來就有一個適配器模式的例子:
~~~
int pow(int i, int j);
int square(int i)
{
return pow(i, 2);
}
~~~
上面的代碼中square函數計算一個整數的平方,這個函數的接口被轉換成計算一個整數的任意整數次冪。在學術圈里這種簡單的技術就被叫做currying(因為邏輯學家[哈斯凱爾·加里](http://zh.wikipedia.org/wiki/%E9%80%82%E9%85%8D%E5%99%A8%E6%A8%A1%E5%BC%8F)用其數學技巧將這種技術描述出來,于是就以他的名字來命名了)。在一個FP語言中函數(而不是類)被作為參數進行傳遞,currying常常用于轉化一個函數的接口以便于其他代碼調用。函數的接口就是它的參數,于是currying通常用于減少函數參數的數量(見前例)。
函數式語言生來就支持這一技術,于是沒有必要為某個函數手工創建另外一個函數去包裝并轉換它的接口,這些函數式語言已經為你做好了。我們繼續拓展Java來支持這一功能。
~~~
square = int pow(int i, 2);
~~~
上面的語句實現了一個平方計算函數,它只需要一個參數。它會繼而調用pow函數并且把第二個參數置為2。編譯過后將生成以下Java代碼:
~~~
class square_function_t {
int square(int i) {
return pow(i, 2);
}
}
square_function_t square = new square_function_t();
~~~
從上面的例子可以看到,很簡單的,函數pow的封裝函數就創建出來了。在FP語言中currying就這么簡單:一種可以快速且簡單的實現函數封裝的捷徑。我們可以更專注于自己的設計,編譯器則會為你編寫正確的代碼!什么時候使用currying呢?很簡單,當你想要用適配器模式(或是封裝函數)的時候,就是用currying的時候。