Scheme 程序语言介绍之一
Scheme 的前身是 Lisp。和 Scheme 一样,这也是一门诞生在 MIT 人工智能实验室的语言。据说 Lisp 在程序语言的族谱上,班辈仅次于 Fortran,是第二古老的语言。但和 Fortran 不同,Fortran 经常被大名鼎鼎的计算机科学家批评,作为反面教材,这些计算机科学家当中有著名的图灵奖获得者 Edsger Dijkstra。而 Lisp 和 Scheme 恰恰相反,它们常被计算机科学家作为正面例子,一个优秀作品的例子。赞扬 Lisp 的人当中有 Smalltalk 和图形用户界面的发明人之一 Alan Kay。
Lisp 由图灵奖获得者 John McCarthy 发明。据说一开始 McCarthy 只想把这门他正在设计的语言的语法的设计,往后拖一拖,等到后面有趣的工作做完了,再回头来给这门基于 Lambda 演算的程序语言加上为数学家们所熟悉的语法。可是 McCarthy 的一个学生很快发现,直接在还没有正式语法的抽象语法里面写程序,感觉非常好。就用不着一个正式的语法了。于是 Lisp 诞生了。Lisp 重要的特征就是:第一,基于 Lambda 演算的计算模型;第二,加上 List processing,这也是 Lisp 名称的由来;第三,直接在抽象语法里面工作,这是非常特别的。前两个重要特征,是 McCarthy 天才的设计,第三个特征则是有趣的巧合。
又过了十多年,还在 MIT 人工智能实验室,不过这次不是 McCarthy,而是两个更年轻的计算机科学家。Guy Steele, Jr. 和他的老师 Gerald Sussman 合作对古典 Lisp 做了两个重要改进。一是把 Lisp 从 Dynamic scope 变成了 Lexical scope。现在大家熟悉的几乎所有的语言都是 Lexical scope,所以大家见怪不怪了。后来 Steele 成为 Common Lisp 设计的主力,Common Lisp 把 Scheme 的 Lexical scope、还有其它一些由 Scheme 所创造的特征,都加入到主流 Lisp 语言当中,Dynamic scope 终于成为了历史。Steele 和 Sussman 做的另一个主要改进是把 Continuation 这个概念引入到程序语言里面。这样一门新的程序语言就此诞生。他们按照人工智能实验室的传统,把它命名为 Scheme。
Steele 和 Sussman 发明了 Scheme 以后,写了份 Report on Scheme。后来经过修改,又 发布了 Revised Report on Scheme,这样不停的 Revise 下去。根据大师们历史悠久的找 乐子的光荣传统,这一系列的 Report 被依次命名为 R2RS、R3RS、R4RS 和目前最新的 R5RS。现在还没有听说 R6RS 的消息。R4RS 是 IEEE 制定的 Scheme 语言标准的基础。 R5RS 比起这个 IEEE 标准,主要增添了"卫生(Hygenic)"的 Macro 支持。
传统 Lisp 的 Macro,在 R5RS 的作者们看来,有严重的缺陷,这促使他们在 R5RS 中发明了"卫生"的 Macro。可是这个卫生的 Macro,反过来又遭到了传统 Lisp 支持者的严厉批评。
Lambda
如果不是专门研究 Lambda 演算的理论,Lambda 对于今天的程序员来说,几乎是个透明而不可见的概念。实在是太普通,都很难把它说的有趣一点,或者看上去深奥一点。因为所谓Lambda,其实就是表达了区区一个"函数"的概念而已。不过,在 Scheme 里面,Lambda 还是表达了两个值得注意的重要特征。第一个,就是广泛的允许匿名对象的存在。这很难说 和正宗的 Lambda 演算的理论有特别的联系,它更像是由 Lambda 演算的理论所衍生出来的编程风格。第二个特征,就是所谓的高阶函数。这个特征和 Lambda 演算理论息息相关。高阶函数是 Lambda 演算理论的精髓,是由 Lisp 首先介绍到程序语言这个世界的。也是大量的现代语言,比如流行的 Python 当中一个似乎是不那么引人注目的特征。
高阶函数(high order function)
高阶函数有两点内容。第一是让函数对象成为程序语言当中所谓"第一等公民"。我们所说 程序语言当中的"第一等公民",指的是可以对这样的数据对象进行赋值、传递等操作。就 像我们可以对整数型变量所做的那样。如果函数对象也是程序语言当中的第一等公民,我们 就可以像上面列举的 Python 的例子那样,把函数对象在变量之间进行赋值和传递等操作。
高阶函数的第二点内容是像下面这样。既然函数本身,就像整数或者浮点数那样,成了我们 所谓"第一等公民",我们当然就希望可以像以前能够做的那样,在我们需要的时候,把所 有这些"第一等公民",拿在手上揉来揉去、捏来捏去,无论它们是整数型数据、或者是浮 点型数据、还是函数型数据。我们要把它们这样变换过来,再那样变换过去。把这些"第一 等公民"放到我们的变换函数里面,对它们进行任意的、我们所需要的各种各样的操作。换 句话说,我们可以像对待整数和浮点型数据那样,把函数本身也作为某个函数的输入数据和 输出数据。也就是说,我们的函数可以对函数本身进行操作。这些可以操作别的函数的函数 的地位不就是更高级了吗?这就是所谓"高阶"这个词的由来。
沒有留言:
張貼留言