38.4. Lambda表达式

[2]经过一系列的陈述与铺垫,终于到正题了。是该讨论一下函数式编程的精髓与理论基础:Lambda表达式了。

让我们将历史的时钟拨回到 19世纪30年代。远比目前“金融危机”严重的多的大萧条正在蹂躏着那个时代的人们,空前的经济下挫影响着几乎所有阶层的家庭生活,只有少数人还能够保持着饥谨危机前的安逸。一些人就如此幸运地位列其中,我们关心的是普林斯顿大学的数学家们。

采用了歌特式风格设计建造的新办公室给普林斯顿罩上天堂般的幸福光环,来自世界各地的逻辑学家被邀请到普林斯顿建设一个新的学部。虽然彼时的美国民众已难能弄到一餐的面包,普林斯顿的条件则是可以在高高的穹顶下,精致雕凿的木质墙饰边上整日的品茶讨论或款款慢步于楼外的林荫之中。

阿隆左•丘奇就是一个在这种近于奢侈的环境中生活着的数学家。他在普林斯顿获得本科学位后被邀留在研究生院继续攻读。阿隆左认为那里的建筑实属浮华,所以他很少一边喝茶一边与人讨论数学,他也不喜欢到林中散步。阿隆左是一个孤独者:因为只有一个人时他才能以最高的效率工作。虽然如此,他仍与一些普林斯顿人保持的定期的联系,其中包括阿兰•图灵,约翰•冯•诺依曼,和 Kurt Grodel。

这四个人都对形式系统很感兴趣,而不太留意现实世界,以便致力于解决抽象的数学难题。他们的难题有些共同之处:都是探索关于计算的问题。如果我们有了无限计算能力的机器,哪些问题可以被解决?我们可以使他们自动地得以解决吗?是否还是有些问题无法解决,为什么?不同设计的各种机器是否具有相同的计算能力?

通过和其它人的合作,阿隆左•丘奇提出了一个被称为 lambda 演算的形式系统。这个系统本质上是一种虚拟的机器的编程语言,他的基础是一些以函数为参数和返回值的函数。函数用希腊字母 lambda 标识,这个形式系统因此得名。利用这一形式系统,阿隆左就可以对上述诸多问题推理并给出结论性的答案。

独立于阿隆左,阿兰•图灵也在进行着相似的工作,他提出了一个不同的形式系统(现在被称为图灵机),并使用这一系统独立给出了和阿隆左相似的结论。后来被证明图灵机和 lambda 演算能力等同。

此时,第二次世界大战打响了,整个世界笼罩在战争的火光和硝烟之中,美国陆军和海军前所未有的大量使用炮弹,为了改进炮弹的精确度,军队组织了大批的科学家持续地计算微分方程以解出弹道发射轨迹。在渐渐意识到这个任务用人力手工完成太耗精力后,人们开始着手开发各种设备来攻克这个难关。第一个解出了弹道轨迹的机器是 IBM 制造的 Mark I —— 它重达5吨,有75万个组件,每秒可以完成三次操作。

竞争当然没有就此结束,1949年,EDVAC(Electronic Discrete Variable Automatic Computer,爱达瓦克)被推出并获得了极大的成功。这是对冯•诺依曼架构的第一个实践实例,实际上也是图灵机的第一个现实实现。那一年好运与阿隆左•丘奇无缘。

直到1950年代将尽,一位 MIT 的教授John McCarthy(也是普林斯顿毕业生)对阿隆左•丘奇的工作产生了兴趣。1958年,他公开了表处理语言 Lisp。Lisp 是对阿隆左•丘奇的 lambda 演算的实现但同时它工作在冯•诺依曼计算机上!很多计算机科学家认识到了 Lisp 的表达能力。1973年,MIT人工智能实验室的一组程序员开发了被称为Lisp机器的硬件-阿隆左 lambda 演算的硬件实现,而Lisp则是函数式程序语言的典型代表。

让我们从历史回忆中醒来,笔者只想告诉你的是:Lambda表达式是函数式编程的理论基础,ELite同样如此。

那么,到底什么是Lambda表达式呢?

在ELite中,Lambda表达式使用运算符 =>,该运算符读为“goes to”,运算符的左边是输入参数(如果有),右边包含表达式或语句块。如:Lambda 表达式 x ,y => x + y 读作“x、y goes to x plus y”。这个表达式需要两个实际参数,因此对它直接求值是得不到结果的,但我们可以使用define指令将一个lambda表达式和一个变量建立关联,这样就可以使用这个变量对lambda表达式进行求值,例如:

> define sum = { x, y => x + y };
> sum(1,2);
3
>

但这种定义方式看上去有点罗嗦,所有ELite中还提供了一种精简方式,上面的定义可以重写成下面的格式,它们是完全等价的。这是ELite为您提供的第一块语法糖。

> define sum(x,y) => x + y;
> sum(1,2);
3

上面的定义已经非常精简,但对您,一名有经验的Java程序员来说,未必习惯,因此,我们又为您提供了第二块语法糖:

> define sum(x,y){ x+y }
> sum(1,2);
3
>

至此,您可能已经看出来一些端倪:上述的代码块,就是我们常规意义上的函数。



[2] 上述文字摘自:Functional Programming For The Rest of Us(http://www.defmacro.org/ramblings/fp.html ),感谢作者:Vyacheslav Akhmechet、译者lihaitao为我们奉献了如此精美的文字。