在 J. McCarthy 离开 MIT 到 Stanford 的时候,很多他以前的研究生被其他大学和研究机构雇佣。Bobrow 两兄弟工作于 Bolt, Beranek and Newman,一个美国研究公司。D. Bobrow 加入了在 California 的 Xerox Palo Alto 研究中心(PARC)。一段时间内在这两个机构都维持着一个联合开发的 Lisp 系统(Interlisp - Teitelman (1974))。Interlisp 也用在 Stanford 大学,在这里它成长为今天能获得的最复杂的 Lisp 系统(大约 600 个预定义函数),带有大量的工具和被认为最用户友好的环境[Sandewall (1978), Teitelman 和 Masinter (1981)]。这个系统的一个更新版本(Interlisp-D)后来在 Xerox “Lisp 机器”上(就是 Dandelion, Dorado 和 Dolphin),还被移植到 Siemens 和 IBM 设备上。
Bobrow 两兄弟的第二个,R. Bobrow,最终担任 California 大学在 Irvine (UCI)的教师,在这里他开发了 UCI-Lisp [Meehan (1979)],这是在很多研究机构流行的方言。在很多年中 UCI-Lisp 充当 Carnegie Mellon 大学的 AI 程序的主要编程工具。
自从捐赠了第一个 PDP6 到 MIT 的计算实验室,DEC10 行列的机器在整个世界成为 AI 研究的标准设备; 同样的,Lisp 被控制为一个编程工具。这种现象可以部分的由它被设计为一个真正分时机器的事实来解释,当时多数其他厂商的设备仍是面向批处理的。快速人/机交互被强制为支持 AI 的典型编程风格。另一个起作用的因素在于主要的 AI 中心(MIT、Stanford、Carnegie Mellon、Edinburgh)使用这些机器用于他们大批的工作的事实;使得要运行他们的软件的拷贝就必须是选用 Lisp,而它又是自由发布的。在七十年代后期和八十年代的 Unix 操作系统的流行日益增长,仍然在 DEC 的小型机行列上产生了大量的 Lisp 实现。 PDP11 Lisp,再次基于 MacLisp,在 Harvard 开发出来。当它的一些职员去 California 大学 Berkeley 分校的时候被拿到了美国西海岸,这里已经对 Unix 有了强烈的兴趣。FranzLisp [Foderaro (1979)]是最终出现的方言。它是基于 Unix 的并运行在 VAX 和其他在大学环境流行的机器上(比如 Suns, ...)。它的持续流行很大程度归功于它的低大学使用价格。
最近在标准化上的兴趣复兴了,很大程度上受使用 Lisp 作为专家系统开发工具的刺激。很多主要计算机厂商委托设计叫做 Common Lisp 的“标准” Lisp 变体[Steele (1984)]。“最初的目标是规定足够接近 MacLisp 后代家族的每个成员的 Lisp,保证这些实现乐于朝向这个公共定义来发展自身。... 委员会的一个主要的子目标是用这个 COMMON LISP 写的程序可以实现直接的源码-可传送,而不用管下层硬件” [Brooks 和 Gabriel (1984), p. 1]。迄今为止这个计划好象成功了。现在已经存在了很多实现。但是,仍有待观察对规整 Lisp 以前不受限制的“特征”增加的尝试是否最终会成功[Allen (1987)]。仍有怀疑的余地,因为多数 Lisp 程序员是高度个人主义的,在风格问题上带有强烈的信念,因为 Lisp 使实现“新”特征非常容易。已经有对 Common Lisp 的大小和它的更加不可思议特征(经常包括它们来确保与过去兼容)的普遍批评。但是,这是一个好机会,商业压力将至少导致一个公共基础,更加专门的方言或子集可以萌发于此,还有一个希望,反映在朝向 ISO Lisp 标准的努力上。
新出现的方言之一是 Scheme,一个词法作用域版本的 MacLisp(象 NIL, T, ..)。Scheme 在 MIT 用来讲授计算机编程的介绍性课程,并在 Abelson 等人(1985)的一本优秀的书中被加以良好的文档。从作者的观点看来 Scheme 是一个非常有表现力的和优雅的语言,围绕着一个简单的小核心,准备了正交性和非常灵活的特征。嵌入到适当的交互编程环境中,它在实践上反击了通常针对 Lisp 的所有批评。它唯一的缺点在于缺乏与传统的 Lisp 系统特别是 Common Lisp 的兼容性。
并行处理近些年已经成为主要的研究焦点,由此产生了很多语言提议。MultiLisp [Halstead (1985)] 是一个有趣的基于 Scheme 的例子。
用 Scheme 编程
Posted-Date: Mon, 6 Jul 87 07:46:39 EDT Date: Mon, 6 Jul 87 07:46:39 EDT From: Tigger@Hundred-Acre-Woods.Milne.Disney To: ramsdell@linus.uucp Subject: Scheme
关于 Scheme 的美妙的事情是: Scheme 是一个漂亮的东西。 复杂的过程式的想法 可以通过简单字符串来表达。 它清晰的语义,和缺乏书生气, 有助于使程序运行,运行,再运行! 然而关于 Scheme 的最美妙的事情是: 用它编程很好玩, 用它编程太好玩了! [Ramsdell (1987)]
概述
Scheme 由 G.J. Sussman 和 G.L. Steele Jr. (1975)在 MIT 设计和实现,作为理解计算的演员模型努力的一部分[Hewitt (1977)]。它是小而紧凑的语言,但是它的概念可以按高度正交性的方式组合和扩展。
C-Scheme [MIT (1984)] 是最初 MIT 实现的最新版本。Scheme 311 [Clinger (1984)] 在 Indiana 大学开发并最终演化成 Chez Scheme [Dybvig and Smith (1985)]。Scheme 84 [Friedman et al. (1984)] 是 Indiana 大学的另一个 Scheme 计划,主要用于实验新颖的控制结构;比如“引擎”概念。T [Slade (1987), Rees et al. (1984)] 是对效率由特殊强调的一个扩展的 Scheme 系统。它是在 Yale 大学开发的。所有这些实现都设计为运行在基于 Unix 的系统上,特别是在 Vax 和 Sun 计算机上。编程通常由标准的编辑器来支持,比如 Emacs,并有一些简单的实用工具用做错误跟踪和调试。针对个人工作站的实现通常提供更加方便的程序环境。PC-Scheme [Bartley and Jensen (1986), Wong (1987)] 在 Texas Instruments 写成,用于 IBM PCs 和 DOS-兼容微机。它包括一个 Emacs-式样的编辑器(Edwin)和一个简单的调料包(Scoops)。MacScheme [Semantic Microsystems (1986), Hartheimer (1987)] 为 Apple MacIntosh 提供一个集成的 Scheme 环境。
Rees & Clinger (1986) 的“Revised Report on Scheme”担任了标准,并被推荐为一个卓越的、简明的和非常可读的语言定义。在本书中的多数程序用 MacScheme、PC Scheme、ChezScheme 和 T 测试过了,尽管 MacScheme 被用做主要的开发工具。出于对可移植性的关心,尽可能的避免了非本质特征。
与其他 Lisp 方言形成对比,Scheme 支持显式的变量定义和词法作用域。语言提供“尾部递归”的高效实现,并提供“续体(continuation)”来定义新的控制结构。所有 Scheme 的对象被作为“一等公民”来对待,这意味这没有武断的限制对象可以做什么和它们要用在那里。任何一类对象可以赋值为变量的值,传递为给过程的参数,返回为一个结果,和存储在复合数据结构中。依据这个定义在多数其他语言中过程被明确的作为“二等公民”对待,包括 Lisp 的早期版本。Clinger (1988b) 提供了对这个概念的深度讨论。
表示和解释 - 符号 & 值
词法作用域和一级过程的组合培养强调模块性和数据抽象的编程风格。Scheme 程序可以看作一组嵌套的表达式,可能引用到一些定义,而这些定义自身可能包含更多的表达式。每个表达式都关联着一个环境,它定义“在作用域中”所有绑定。 (define MeaningOfLife 42)
(+ MeaningOfLife 7)
例子是有两个表达式的一个“程序”,其中第一个表达式把系统提供的 define 过程应用到一个标识符和作为它的参数的一个值。
在下面的讨论中,我们将使用粗体字来标记被系统以某种预先定义的方式使用的所有标识符。对所有的系统响应前导上一个分号(;)。在我们把精力转移到这个程序的执行之前,还要注意一些其他事情。Scheme 对标识符不做长度限制。它们必须开始于不能开始数字的一个字符,并可以包含任意树木的字母、数字和所谓的“扩展字母表字符”字符。* / < = > ! ? : $ % _ & ~ ^ 被作为这种扩展字母表字符对待。一些标识符充当语法关键字而不应当用做变量。注释开始于一个 ; 并延伸到行结束。它们被解释器所忽略。还有一个语法惯例,所有重新绑定变量的过程应当以 ! 结束,而以 ? 结束的所有过程都返回 #t 或 #f (用做“真”和“假”)。
Scheme 解释器以 Lisp 的经典的“读,求值,打印”周期的方式操作;就是说,它将读一个表达式,尝试求值它,并显示结果。在执行期间假定,除非被引用,否则把原子求值为它们的绑定,并且表结构指示函数对参数的“应用” (所以叫“应用式语言”)。依据“Cambridge Polish”的惯例解释器将尝试对表的第一个元素关联上一个过程,把它应用到所有随后的参数上。
与解释器的交互通常在某种支持编程的环境中通过所谓的记录器(transcript)进行。在这里键入表达式并打印解释器的回应。通常提供编辑器层次的语法支持;比如,系统将按照键入适当的缩进定义,并且“闪烁”匹配的圆括号。这种特征对于有如此稀少语法的语言是绝对本质性的。
表达式可以被键入和求值,还可以滚动窗口的内容来查看前面交互的结果。这种外在形式(figure)也示范了 MacScheme 的 3 类菜单。File 菜单涉及建立、装载、更新和打印文件的动作,还用于退出系统。Edit 菜单与鼠标驱动的编辑器交互。它提供用来剪切和粘贴的命令,还有用来选择一个表达式“直到”匹配的左括号("pick")和强制重新缩进(表达式通常按照它们键入的样子来缩进)。Command 菜单特定于 MacScheme,而其他两个菜单类似于其他 MacIntosh 软件的 File 和 Edit 菜单。有用来求值被选择了的表达式,和用来打断和继续执行的命令。“选择”可以使用 "pick" (在 Edit 菜单中),也可以通过在光标已经定位于表达式的最右圆括号之后按住“enter”来完成。打断一个过程的执行将调用一个调试器,而 "pause"将简单的停止这个程序。在已经修正了错误条件之后,可以使用 "Reset" 来返回控制到“顶层”来继续一个会话。MacScheme 允许我们打开最多 4 个独立窗口。其中之一将总是记录器,而其他可以提供对文件内容的编辑器。表达式的选择和求值也可以发生在这种窗口中。表达式将接着被复制到记录器中而结果值将在记录器中显示)。这通常会导致在记录器中的文本增长的非常长,所以它的内容应当不时的被“修整”。最后,因为标准的 MacIntosh 屏幕非常小,有一个命令当记录器被其他窗口掩盖的时候用来显示它。其他 Scheme 方言也提供类似的、但经常不是很彻底的东西,用做方便的程序员界面。
在上述程序被求值的时候,它将导致建立一个环境,MeaningOfLife 在其中绑定(到 42)。随后的表达式将接着在这个环境的作用域内进行一次加法,返回值“42”。还要注意所有表达式都必须产生一个值,它总是要打印出来。它通常是被求值的最后一个项目的值,当然,有时这不是想要的行为;就是说,我们可能经常希望强制解释器按字面接受某些数据。可以使用 quote 函数来获得这种效果,比如 (quote (define MeaningOfLife 42))
; (define MeaningOfLife 42)
因为引用是极其常见的操作,提供了一个简写。用来减少大量的圆括号。可以使用一个前置(prime)的 (')来指示引用。 '(define MeaningOfLife 42)
;(define MeaningOfLife 42)
当然,还应当有取消这种引用的方法。Lisp 的 eval 提供这种功能。与 Lisp 不同的是,这个函数不被很多 Scheme 方言所支持。这反映了使用 eval 使有选择的代码连接很困难的事实,甚至对于单独的应用程序是不可能的,而要求在执行时获得“完全的” Scheme 系统。多数时候它都不是必须的,因为通常可以用不同的方法完成同样的效果。在 MacScheme 中能获得 eval,但是我们要克制对它的使用。不恰当的使用引用和求值是程序错误的非常多产的来源,它很快就会成为对于所有初学者显见的痛苦。它对增值这些操作建造于其上的基本模型是重要的。如同汇编语言,Scheme 在数据和程序之间不加以语法上的区别。只在指定的解释上下文中决定符号的“意义”。符号要么在字面上要么通过关联(association)指示(denote)对象。在执行期间将获得符号的绑定,而数值、逻辑值、字符、字符串和向量求值为自身。
数据类型和它们的操作
Scheme 提供的文字类型有数值、逻辑值、字符、字符串、符号、表、向量和 lambda 表达式。
|