## 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的时候。