您的位置:首页 > 编程语言

函数式编程里的currying柯里化

2013-07-02 00:00 363 查看
我认识的大多数人都读过“四人帮”的那本设计模式,任何有自尊的程序员都会告诉你那本书是语言中立的(agnostic),模式在软件工程中是通用的,和使用的语言无关。这个个高贵的宣言,但不幸有违现实。

函数式编程具有突出的表达能力,在函数式语言中,语言已达此高度,设计模式就不再是必需,最终你将能消灭设计模式而以概念编程。适配器 (Adapter)模式就是这样的一个例子(究竟适配器和 Facade 模式区别在哪里?可能有些人需要在这里再多费些篇章),而一旦语言有了叫作 currying (柯里化)的技术,这一模式就可以被消除。

适配器模式最有名的是被应用在 Java 的“默认”行为抽象上。在函数式编程里,模式被应用到函数,模式带有一个接口并将它转换成另一个对他人有用的接口。这有一个适配器模式的例子:

int pow(int i, int j);
int square(int i)
{
return pow(i, 2);
}

上面的代码把一个整数幂运算接口转换成为了一个平方接口。在学术文章里,这个雕虫小技被叫作 currying(得名于逻辑学家 Haskell Curry,他曾将相关的数学理论形式化)。因为在函数式编程中函数(反之如 class)被作为参数来回传递,currying 很频繁地被用来把函数调整为更适宜的接口。因为函数的接口是他的参数,使用 currying 可以减少参数的数目(如上例所示)。

函数式语言内建了这一技术。不用手动地创建一个包装了原函数的函数,函数式语言可以为你代劳。同样地,扩展我们(假想)的 Java 语言,让他支持这个技术:

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?这很简单,任何时候你想要使用适配器模式(包装)时。

关于柯里化(currying),我们可以这么理解:柯里化就是一个函数在参数没给全时返回另一个函数,返回的函数的参数正好是余下的参数。比如:你制定了x和y, 如2的3次方,就返回8, 如果你只制定x为2,y没指定, 那么就返回一个函数:2的y次方, 这个函数只有一个参数:y。这样就非常容易理解吧。

PS:该概念来自 Alonzo Church 的 Lambda calculus,它的 2 大特性:

匿名函数

每个函数只有一个输入参数
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: