The following part is not maintained anymore. Please go to 函数式程序设计的另类指南 for the whole translation.
以下内容不再更新,浏览全部翻译,请访问 函数式程序设计的另类指南
原文链接:Functional Programming For The Rest of Us
原文作者:Vyacheslav Akhmechet
Currying
我认识的很多人都读过四人帮(GOF)的《设计模式》。任何自恋的程序员都会告诉你,这本书中讨论的模式在软件工程中具有通用性,它和使用哪门语言无关。这个说法显得颇为高深,但是有违现实。
函数式编程极具表达能力。你不需要在函数式语言中使用设计模式,因为这种高级程序设计语言可以让你只进行概念编程,从而不再需要设计模式。适配器(Adapter)模式就是这样的一个例子(适配器和外观模式(Facade)有什么区别?某人可能需要在这里高谈扩论了)。一旦语言有了叫作currying的技术,我们就不再需要适配器模式了。
适配器模式最有名的应用是Java的“默认”抽象单元——类。在函数式编程里,这个模式被应用到函数上。适配器模式将一个接口转换为另一个接口。这里有一个适配器模式的例子:
int pow(int i, int j); int square(int i) { return pow(i, 2); }
上面的代码把一个整数幂运算接口转换成为了一个平方接口。在学术圈中,这样的用法被称之为currying(得名于逻辑学家Haskell Curry,他曾将相关的数学理论形式化)。因为在函数式编程中,函数——而不是类——作为参数进行传递,因此可以用currying把函数适配到其他接口。又因为函数的接口就是其参数列表,所以currying可以减少参数的数量(如上例所示)。
因为函数式语言内建了这一技术,所以不用手动地创建一个包装了原函数的类。函数式语言会为你代劳。和之前一样,我们来扩展一下我们的语言来支持这个技术:
square = int pow(int i, 2);
编译器会自动为我们创建一个只有一个参数的square函数。它会在第二个参数为2的情况下调用pow函数。这段代码会编译成如下Java代码:
class square_function_t { int square(int i) { return pow(i, 2); } } square_function_t square = new square_function_t();
正如你所见,我们只是简单地包装了一下原函数。在函数式编程中,这就是currying——快速便捷的包装一个函数。你专注于你的工作,而编译器为你生成具体的代码!那么什么时候用currying?很简单:当你想用适配器模式(包装)的时候。