Chapter 1
第一章
Building Abstractions with Procedures
构造过程抽象
The acts of the mind, wherein it exerts its power over simple ideas, are chiefly these three: 1. Combining several simple ideas into one compound one, and thus all complex ideas are made. 2. The second is bringing two ideas, whether simple or complex, together, and setting them by one another so as to take a view of them at once, without uniting them into one, by which it gets all its ideas of relations. 3. The third is separating them from all other ideas that accompany them in their real existence: this is called abstraction, and thus all its general ideas are made.
心智的活动,除了尽力产生各种简单的认识之外,主要表现在如下三个方面:1)将若干简单认识组合为一个复合认识,由此产生出各种复杂的认识。2)将两个认识放在一起对照。不管它们如何简单或者复杂,在这样做时并不将它们合而为一。由此得到有关它们的相互关系的认识。3)将有关认识与那些在实际中和它们同在的所有其他认识隔离开。这就是抽象,所有具有普遍性的认识都是这样得到的。
John Locke, An Essay Concerning Human Understanding (1690)
We are about to study the idea of a computational process. Computational processes are abstract beings that inhabit computers. As they evolve, processes manipulate other abstract things called data. The evolution of a process is directed by a pattern of rules called a program. People create programs to direct processes. In effect, we conjure the spirits of the computer with our spells.
我们准备学习的是有关计算过程的知识。计算过程是存在于计算机里的一类抽象事物,在其演化进程中,这些过程会去操作一些被为数据的抽象事物。人们创建出一些称为程序的规则模式,以指导这类过程的进行。从作用上看,就像是我们在通过自己的写作魔力去控制计算机里的精灵似的。
A computational process is indeed much like a sorcerer's idea of a spirit. It cannot be seen or touched. It is not composed of matter at all. However, it is very real. It can perform intellectual work. It can answer questions. It can affect the world by disbursing money at a bank or by controlling a robot arm in a factory. The programs we use to conjure processes are like a sorcerer's spells. They are carefully composed from symbolic expressions in arcane and esoteric programming languages that prescribe the tasks we want our processes to perform.
一个计算过程确实很像一种神灵的巫术,它看不见也摸不到,根本就不是由物质组成的。然而它却又是非常真实的,可以完成某些智力性的工作。它可以回答提问,可以通过在银行里支付现金或者在工厂里操纵机器人等等方式影响这个世界。我们用于指挥这种过程的程序就像是巫师的咒语,它们是用一些诡秘而深奥的程序设计语言,通过符号表达式的形式精心编排而成,它们描述了我们希望相应的计算过程去完成的工作。
A computational process, in a correctly working computer, executes programs precisely and accurately. Thus, like the sorcerer's apprentice, novice programmers must learn to understand and to anticipate the consequences of their conjuring. Even small errors (usually called bugs or glitches) in programs can have complex and unanticipated consequences.
在正常工作的计算机里,一个计算过程将精密而准确地执行相应的程序。这样,初学程序设计的人们就像巫师的徒弟们那样,必须学习如何去理解和预期他们所发出的咒语的效果。程序里即使有一点小错误(常常被称为程序错误或者故障),也可能产生复杂而无法预料的后果。
Fortunately, learning to program is considerably less dangerous than learning sorcery, because the spirits we deal with are conveniently contained in a secure way. Real-world programming, however, requires care, expertise, and wisdom. A small bug in a computer-aided design program, for example, can lead to the catastrophic collapse of an airplane or a dam or the self-destruction of an industrial robot.
幸运的是,学习程序的危险性远远小于学习巫术,因为我们要去控制的神灵以一种很安全的方式被约束着。而真实的程序设计则需要极度细心。需要经验和智慧。例如,在一个计算机辅助设计系统里的一点小毛病,就可能导致一架飞机或者一座水坝的灾难性损毁,或者一个工业机器人的自我破坏。
Master software engineers have the ability to organize programs so that they can be reasonably sure that the resulting processes will perform the tasks intended. They can visualize the behavior of their systems in advance. They know how to structure programs so that unanticipated problems do not lead to catastrophic consequences, and when problems do arise, they can debug their programs. Well-designed computational systems, like well-designed automobiles or nuclear reactors, are designed in a modular manner, so that the parts can be constructed, replaced, and debugged separately.
软件工程大师们能组织好自己的程序,使自己能合理地确信这些程序所产生的计算过程将能完成预期的工作。他们可以事先看到自己系统的行为方式,知道如何去构造这些程序,使其中出现的意外问题不会导致灾难性的后果。而且,在发生了这种问题时,他们也能排除程序中的错误。设计良好的计算系统就像设计良好的汽车或者核反应堆一样,具有某种模块化的设计,其中的各个部分都可以独立地构造、替换、排除错误。
Programming in Lisp
用 Lisp 编程
We need an appropriate language for describing processes, and we will use for this purpose the programming language Lisp. Just as our everyday thoughts are usually expressed in our natural language (such as English, French, or Japanese), and descriptions of quantitative phenomena are expressed with mathematical notations, our procedural thoughts will be expressed in Lisp. Lisp was invented in the late 1950s as a formalism for reasoning about the use of certain kinds of logical expressions, called recursion equations, as a model for computation. The language was conceived by John McCarthy and is based on his paper ``Recursive Functions of Symbolic Expressions and Their Computation by Machine'' (McCarthy 1960).
为了描述这类计算过程,我们需要有一种适用的语言。我们将为此使用程序设计语言 Lisp。正如人们每天用自然语言(如英语、法语或日语等)表述自己的想法,用数学形式的记法描述定量的现象一样,我们将要用 Lisp 表述过程性的思想。Lisp 是 20 世纪 50 年代后期发明的一种记法形式,是为了能对某种特定形式的逻辑表达式(称为递归方程)的使用做推理。递归方程可以作为计算的模型。这一语言是由 John McCarthy 设计的,基于他的论文“Recursive Function of Symbolic Expressions and Their Computation by Machine”(符号表达式的递归函数及其机械计算,McCarthy 1960)。
Despite its inception as a mathematical formalism, Lisp is a practical programming language. A Lisp interpreter is a machine that carries out processes described in the Lisp language. The first Lisp interpreter was implemented by McCarthy with the help of colleagues and students in the Artificial Intelligence Group of the MIT Research Laboratory of Electronics and in the MIT Computation Center. 1 Lisp, whose name is an acronym for LISt Processing, was designed to provide symbol-manipulating capabilities for attacking programming problems such as the symbolic differentiation and integration of algebraic expressions. It included for this purpose new data objects known as atoms and lists, which most strikingly set it apart from all other languages of the period.
虽然在开始时,McCarthy 是想以 Lisp 作为一种数学记述形式,但它确实是一种实用的程序设计语言。一个 Lisp 解释器就像是一台机器,它能实现用 Lisp 语言描述的计算过程。第一个 Lisp 解释器是 McCarthy 在 MIT 电子研究实验室的人工智能组的 MIT 计算中心里他的同事和学生的帮助下实现的 1。Lisp 的名字来自表处理(LISt Processing),其设计是为提供符号计算的能力,以便能用于解决一些程序设计问题,例如代数表达式的符号数微分和积分。它包含了适用于这类目的的一些新数据对象,称为原子和表,这是它与那一时代的所有其他语言之间是明显的不同之外。
Lisp was not the product of a concerted design effort. Instead, it evolved informally in an experimental manner in response to users' needs and to pragmatic implementation considerations. Lisp's informal evolution has continued through the years, and the community of Lisp users has traditionally resisted attempts to promulgate any ``official'' definition of the language. This evolution, together with the flexibility and elegance of the initial conception, has enabled Lisp, which is the second oldest language in widespread use today (only Fortran is older), to continually adapt to encompass the most modern ideas about program design. Thus, Lisp is by now a family of dialects, which, while sharing most of the original features, may differ from one another in significant ways. The dialect of Lisp used in this book is called Scheme. 2
Lisp 并不是一个刻意的设计努力的结果,它以一种试验性的非正式的方式不断深化,以满足用户的需要和实际实现的各种考虑。Lisp 的这种非官方深化持续了许多年,Lisp 用户社团具有抵制制定这一语言的“官方”定义企图的传统。这种演化方式以及语言初始概念的灵活和优美,使得 Lisp 成为今天还在广泛使用的历史第二悠久的语言(只有 Fortran 比它更老)。这一语言还在不断调整,以便去包容有关程序设计的最新思想。正因为这样,今天的 Lisp 已经形成了一族方言,它们共享着初始语言的大部分特征,也可能有这样或那样的重要差异。用于本书的 Lisp 方言名为 Scheme 2。
Because of its experimental character and its emphasis on symbol manipulation, Lisp was at first very inefficient for numerical computations, at least in comparison with Fortran. Over the years, however, Lisp compilers have been developed that translate programs into machine code that can perform numerical computations reasonably efficiently. And for special applications, Lisp has been used with great effectiveness. 3 Although Lisp has not yet overcome its old reputation as hopelessly inefficient, Lisp is now used in many applications where efficiency is not the central concern. For example, Lisp has become a language of choice for operating-system shell languages and for extension languages for editors and computer-aided design systems.
由于 Lisp 的试验性质以及强调符号操作的特点,开始时的这个语言对于数值计算而言是很低效的,至少与 Fortran 比较时是这样。经过这么多年的发展。人们已经开发出了 Lisp 编译器,它们可以将程序翻译为机器代码,这样的代码能相当高效地完成各种数值计算。Lisp 已经可以非常有效地用于一些特殊的应用领域 3。虽然 Lisp 还没有完全战胜有关它特别低效的诋毁,但它现在已被用于许多性能并不是最重要考虑因素的应用领域。例如,Lisp 已经成为操作系统外壳语言的一种选择,作为编辑器和计算机辅助设计系统的扩充语言等等。
If Lisp is not a mainstream language, why are we using it as the framework for our discussion of programming? Because the language possesses unique features that make it an excellent medium for studying important programming constructs and data structures and for relating them to the linguistic features that support them. The most significant of these features is the fact that Lisp descriptions of processes, called procedures, can themselves be represented and manipulated as Lisp data. The importance of this is that there are powerful program-design techniques that rely on the ability to blur the traditional distinction between ``passive'' data and ``active'' processes. As we shall discover, Lisp's flexibility in handling procedures as data makes it one of the most convenient languages in existence for exploring these techniques. The ability to represent procedures as data also makes Lisp an excellent language for writing programs that must manipulate other programs as data, such as the interpreters and compilers that support computer languages. Above and beyond these considerations, programming in Lisp is great fun.
既然 Lisp 并不是一种主流语言,我们为什么要用它作为讨论程序设计的基础呢?这是因为,这一语言具有许多独有的特征,这些特征使它成为研究重要程序的设计、构造,以及各种数据结构,并将其关联于支持它们的语言特征的一种极佳媒介。这些特征之中最重要的就是:计算过程的 Lisp 描述(称为过程)本身又可以作为 Lisp 的数据来表示和操作。这一事实重要性在于,现在的许多威力强大的程序设计技术,都依赖于填平在“被动的”数据和“主动的”过程之间的传统划分。正如我们将要看到的,Lisp 可以将过程作为数据进行处理的灵活性,使它成为探索这些技术的最方便的现在语言之一。能将过程表示为数据的能力,也使 Lisp 成为编写那些必须将其他程序当作数据去操作的程序的最佳语言,例如支持计算机语言的解释器和编译器。除了这些考虑之外,用 Lisp 编程本身也是极其有趣的。
1 The Lisp 1 Programmer's Manual appeared in 1960, and the Lisp 1.5 Programmer's Manual (McCarthy 1965) was published in 1962. The early history of Lisp is described in McCarthy 1978.
1Lisp 1 Programmer's Manual 在 1960 年发表,Lisp 1.5 Programmer's Manual(McCarthy 1965)d 1962 年发表。有关 Lisp 的早期历史见 McCarthy 1978。
2 The two dialects in which most major Lisp programs of the 1970s were written are MacLisp (Moon 1978; Pitman 1983), developed at the MIT Project MAC, and Interlisp (Teitelman 1974), developed at Bolt Beranek and Newman Inc. and the Xerox Palo Alto Research Center. Portable Standard Lisp (Hearn 1969; Griss 1981) was a Lisp dialect designed to be easily portable between different machines. MacLisp spawned a number of subdialects, such as Franz Lisp, which was developed at the University of California at Berkeley, and Zetalisp (Moon 1981), which was based on a special-purpose processor designed at the MIT Artificial Intelligence Laboratory to run Lisp very efficiently. The Lisp dialect used in this book, called Scheme (Steele 1975), was invented in 1975 by Guy Lewis Steele Jr. and Gerald Jay Sussman of the MIT Artificial Intelligence Laboratory and later reimplemented for instructional use at MIT. Scheme became an IEEE standard in 1990 (IEEE 1990). The Common Lisp dialect (Steele 1982, Steele 1990) was developed by the Lisp community to combine features from the earlier Lisp dialects to make an industrial standard for Lisp. Common Lisp became an ANSI standard in 1994 (ANSI 1994).
2在 20 世纪 70 年代,最主要的两个 Lisp 方言是 MIT 的 MAC 项目中开发的 MacLisp(Moon 1978;Priman 1983),以及在 Bolt Beranek and Newman Inc. 和 Xerox Palo Alto Research Center 开发的 Interlisp(Teitelman 1974),那时主要的 Lisp 程序都是用它们写的。Portable Standard Lisp(Hearn 1969;Griss 1981)是另一种 Lisp 方言,其设计就是为能更容易地移植到不同的计算机上。MacLisp 又发展出一些子方言,例如加州大学伯克得分校开发的 Franz Lisp,还有 Zetalisp(Moon 1981),它基于 MIT 人工智能实验室设计的一种专用处理器,这一处理器可以非常高效地运行 Lisp。本书所用的 Lisp 方言称为 Scheme(Steele 1975),是 1975 年由 MIT 人工智能实验室的 Guy Lewis Steele Jr. 和 Gerald Jay Sussman 设计的,后来的 MIT 为了教学使用而重新实现。在 1990 年 Scheme 变成了 IEEE 标准(IEEE 1990)。Common Lisp 方言(Steele 1982,Steele 1990)是由 Lisp 社团综合了早前各种 Lisp 方言的特征而开发出来的,希望能做成 Lisp 的工业标准。Common Lisp 在 1994 年成为 ANSI 标准(ANSI 1994)。
3 One such special application was a breakthrough computation of scientific importance -- an integration of the motion of the Solar System that extended previous results by nearly two orders of magnitude, and demonstrated that the dynamics of the Solar System is chaotic. This computation was made possible by new integration algorithms, a special-purpose compiler, and a special-purpose computer all implemented with the aid of software tools written in Lisp (Abelson et al. 1992; Sussman and Wisdom 1992).
3这方面有一个应用是科学计算的重要突破——有关太阳系运动的整合,它将的结果提高了两个数量级,并显示出太阳系统动力学的混沌性。完成这一计算依靠了一种新的整合算法、一个特殊的编译器以及一台专用计算机,所有这些都是在用 Lisp 写的软件工具的帮助下实现的(Abelson et al. 1992;Sussman 和 Wisdom 1992)。
第一章
Building Abstractions with Procedures
构造过程抽象
The acts of the mind, wherein it exerts its power over simple ideas, are chiefly these three: 1. Combining several simple ideas into one compound one, and thus all complex ideas are made. 2. The second is bringing two ideas, whether simple or complex, together, and setting them by one another so as to take a view of them at once, without uniting them into one, by which it gets all its ideas of relations. 3. The third is separating them from all other ideas that accompany them in their real existence: this is called abstraction, and thus all its general ideas are made.
心智的活动,除了尽力产生各种简单的认识之外,主要表现在如下三个方面:1)将若干简单认识组合为一个复合认识,由此产生出各种复杂的认识。2)将两个认识放在一起对照。不管它们如何简单或者复杂,在这样做时并不将它们合而为一。由此得到有关它们的相互关系的认识。3)将有关认识与那些在实际中和它们同在的所有其他认识隔离开。这就是抽象,所有具有普遍性的认识都是这样得到的。
John Locke, An Essay Concerning Human Understanding (1690)
We are about to study the idea of a computational process. Computational processes are abstract beings that inhabit computers. As they evolve, processes manipulate other abstract things called data. The evolution of a process is directed by a pattern of rules called a program. People create programs to direct processes. In effect, we conjure the spirits of the computer with our spells.
我们准备学习的是有关计算过程的知识。计算过程是存在于计算机里的一类抽象事物,在其演化进程中,这些过程会去操作一些被为数据的抽象事物。人们创建出一些称为程序的规则模式,以指导这类过程的进行。从作用上看,就像是我们在通过自己的写作魔力去控制计算机里的精灵似的。
A computational process is indeed much like a sorcerer's idea of a spirit. It cannot be seen or touched. It is not composed of matter at all. However, it is very real. It can perform intellectual work. It can answer questions. It can affect the world by disbursing money at a bank or by controlling a robot arm in a factory. The programs we use to conjure processes are like a sorcerer's spells. They are carefully composed from symbolic expressions in arcane and esoteric programming languages that prescribe the tasks we want our processes to perform.
一个计算过程确实很像一种神灵的巫术,它看不见也摸不到,根本就不是由物质组成的。然而它却又是非常真实的,可以完成某些智力性的工作。它可以回答提问,可以通过在银行里支付现金或者在工厂里操纵机器人等等方式影响这个世界。我们用于指挥这种过程的程序就像是巫师的咒语,它们是用一些诡秘而深奥的程序设计语言,通过符号表达式的形式精心编排而成,它们描述了我们希望相应的计算过程去完成的工作。
A computational process, in a correctly working computer, executes programs precisely and accurately. Thus, like the sorcerer's apprentice, novice programmers must learn to understand and to anticipate the consequences of their conjuring. Even small errors (usually called bugs or glitches) in programs can have complex and unanticipated consequences.
在正常工作的计算机里,一个计算过程将精密而准确地执行相应的程序。这样,初学程序设计的人们就像巫师的徒弟们那样,必须学习如何去理解和预期他们所发出的咒语的效果。程序里即使有一点小错误(常常被称为程序错误或者故障),也可能产生复杂而无法预料的后果。
Fortunately, learning to program is considerably less dangerous than learning sorcery, because the spirits we deal with are conveniently contained in a secure way. Real-world programming, however, requires care, expertise, and wisdom. A small bug in a computer-aided design program, for example, can lead to the catastrophic collapse of an airplane or a dam or the self-destruction of an industrial robot.
幸运的是,学习程序的危险性远远小于学习巫术,因为我们要去控制的神灵以一种很安全的方式被约束着。而真实的程序设计则需要极度细心。需要经验和智慧。例如,在一个计算机辅助设计系统里的一点小毛病,就可能导致一架飞机或者一座水坝的灾难性损毁,或者一个工业机器人的自我破坏。
Master software engineers have the ability to organize programs so that they can be reasonably sure that the resulting processes will perform the tasks intended. They can visualize the behavior of their systems in advance. They know how to structure programs so that unanticipated problems do not lead to catastrophic consequences, and when problems do arise, they can debug their programs. Well-designed computational systems, like well-designed automobiles or nuclear reactors, are designed in a modular manner, so that the parts can be constructed, replaced, and debugged separately.
软件工程大师们能组织好自己的程序,使自己能合理地确信这些程序所产生的计算过程将能完成预期的工作。他们可以事先看到自己系统的行为方式,知道如何去构造这些程序,使其中出现的意外问题不会导致灾难性的后果。而且,在发生了这种问题时,他们也能排除程序中的错误。设计良好的计算系统就像设计良好的汽车或者核反应堆一样,具有某种模块化的设计,其中的各个部分都可以独立地构造、替换、排除错误。
Programming in Lisp
用 Lisp 编程
We need an appropriate language for describing processes, and we will use for this purpose the programming language Lisp. Just as our everyday thoughts are usually expressed in our natural language (such as English, French, or Japanese), and descriptions of quantitative phenomena are expressed with mathematical notations, our procedural thoughts will be expressed in Lisp. Lisp was invented in the late 1950s as a formalism for reasoning about the use of certain kinds of logical expressions, called recursion equations, as a model for computation. The language was conceived by John McCarthy and is based on his paper ``Recursive Functions of Symbolic Expressions and Their Computation by Machine'' (McCarthy 1960).
为了描述这类计算过程,我们需要有一种适用的语言。我们将为此使用程序设计语言 Lisp。正如人们每天用自然语言(如英语、法语或日语等)表述自己的想法,用数学形式的记法描述定量的现象一样,我们将要用 Lisp 表述过程性的思想。Lisp 是 20 世纪 50 年代后期发明的一种记法形式,是为了能对某种特定形式的逻辑表达式(称为递归方程)的使用做推理。递归方程可以作为计算的模型。这一语言是由 John McCarthy 设计的,基于他的论文“Recursive Function of Symbolic Expressions and Their Computation by Machine”(符号表达式的递归函数及其机械计算,McCarthy 1960)。
Despite its inception as a mathematical formalism, Lisp is a practical programming language. A Lisp interpreter is a machine that carries out processes described in the Lisp language. The first Lisp interpreter was implemented by McCarthy with the help of colleagues and students in the Artificial Intelligence Group of the MIT Research Laboratory of Electronics and in the MIT Computation Center. 1 Lisp, whose name is an acronym for LISt Processing, was designed to provide symbol-manipulating capabilities for attacking programming problems such as the symbolic differentiation and integration of algebraic expressions. It included for this purpose new data objects known as atoms and lists, which most strikingly set it apart from all other languages of the period.
虽然在开始时,McCarthy 是想以 Lisp 作为一种数学记述形式,但它确实是一种实用的程序设计语言。一个 Lisp 解释器就像是一台机器,它能实现用 Lisp 语言描述的计算过程。第一个 Lisp 解释器是 McCarthy 在 MIT 电子研究实验室的人工智能组的 MIT 计算中心里他的同事和学生的帮助下实现的 1。Lisp 的名字来自表处理(LISt Processing),其设计是为提供符号计算的能力,以便能用于解决一些程序设计问题,例如代数表达式的符号数微分和积分。它包含了适用于这类目的的一些新数据对象,称为原子和表,这是它与那一时代的所有其他语言之间是明显的不同之外。
Lisp was not the product of a concerted design effort. Instead, it evolved informally in an experimental manner in response to users' needs and to pragmatic implementation considerations. Lisp's informal evolution has continued through the years, and the community of Lisp users has traditionally resisted attempts to promulgate any ``official'' definition of the language. This evolution, together with the flexibility and elegance of the initial conception, has enabled Lisp, which is the second oldest language in widespread use today (only Fortran is older), to continually adapt to encompass the most modern ideas about program design. Thus, Lisp is by now a family of dialects, which, while sharing most of the original features, may differ from one another in significant ways. The dialect of Lisp used in this book is called Scheme. 2
Lisp 并不是一个刻意的设计努力的结果,它以一种试验性的非正式的方式不断深化,以满足用户的需要和实际实现的各种考虑。Lisp 的这种非官方深化持续了许多年,Lisp 用户社团具有抵制制定这一语言的“官方”定义企图的传统。这种演化方式以及语言初始概念的灵活和优美,使得 Lisp 成为今天还在广泛使用的历史第二悠久的语言(只有 Fortran 比它更老)。这一语言还在不断调整,以便去包容有关程序设计的最新思想。正因为这样,今天的 Lisp 已经形成了一族方言,它们共享着初始语言的大部分特征,也可能有这样或那样的重要差异。用于本书的 Lisp 方言名为 Scheme 2。
Because of its experimental character and its emphasis on symbol manipulation, Lisp was at first very inefficient for numerical computations, at least in comparison with Fortran. Over the years, however, Lisp compilers have been developed that translate programs into machine code that can perform numerical computations reasonably efficiently. And for special applications, Lisp has been used with great effectiveness. 3 Although Lisp has not yet overcome its old reputation as hopelessly inefficient, Lisp is now used in many applications where efficiency is not the central concern. For example, Lisp has become a language of choice for operating-system shell languages and for extension languages for editors and computer-aided design systems.
由于 Lisp 的试验性质以及强调符号操作的特点,开始时的这个语言对于数值计算而言是很低效的,至少与 Fortran 比较时是这样。经过这么多年的发展。人们已经开发出了 Lisp 编译器,它们可以将程序翻译为机器代码,这样的代码能相当高效地完成各种数值计算。Lisp 已经可以非常有效地用于一些特殊的应用领域 3。虽然 Lisp 还没有完全战胜有关它特别低效的诋毁,但它现在已被用于许多性能并不是最重要考虑因素的应用领域。例如,Lisp 已经成为操作系统外壳语言的一种选择,作为编辑器和计算机辅助设计系统的扩充语言等等。
If Lisp is not a mainstream language, why are we using it as the framework for our discussion of programming? Because the language possesses unique features that make it an excellent medium for studying important programming constructs and data structures and for relating them to the linguistic features that support them. The most significant of these features is the fact that Lisp descriptions of processes, called procedures, can themselves be represented and manipulated as Lisp data. The importance of this is that there are powerful program-design techniques that rely on the ability to blur the traditional distinction between ``passive'' data and ``active'' processes. As we shall discover, Lisp's flexibility in handling procedures as data makes it one of the most convenient languages in existence for exploring these techniques. The ability to represent procedures as data also makes Lisp an excellent language for writing programs that must manipulate other programs as data, such as the interpreters and compilers that support computer languages. Above and beyond these considerations, programming in Lisp is great fun.
既然 Lisp 并不是一种主流语言,我们为什么要用它作为讨论程序设计的基础呢?这是因为,这一语言具有许多独有的特征,这些特征使它成为研究重要程序的设计、构造,以及各种数据结构,并将其关联于支持它们的语言特征的一种极佳媒介。这些特征之中最重要的就是:计算过程的 Lisp 描述(称为过程)本身又可以作为 Lisp 的数据来表示和操作。这一事实重要性在于,现在的许多威力强大的程序设计技术,都依赖于填平在“被动的”数据和“主动的”过程之间的传统划分。正如我们将要看到的,Lisp 可以将过程作为数据进行处理的灵活性,使它成为探索这些技术的最方便的现在语言之一。能将过程表示为数据的能力,也使 Lisp 成为编写那些必须将其他程序当作数据去操作的程序的最佳语言,例如支持计算机语言的解释器和编译器。除了这些考虑之外,用 Lisp 编程本身也是极其有趣的。
1 The Lisp 1 Programmer's Manual appeared in 1960, and the Lisp 1.5 Programmer's Manual (McCarthy 1965) was published in 1962. The early history of Lisp is described in McCarthy 1978.
1Lisp 1 Programmer's Manual 在 1960 年发表,Lisp 1.5 Programmer's Manual(McCarthy 1965)d 1962 年发表。有关 Lisp 的早期历史见 McCarthy 1978。
2 The two dialects in which most major Lisp programs of the 1970s were written are MacLisp (Moon 1978; Pitman 1983), developed at the MIT Project MAC, and Interlisp (Teitelman 1974), developed at Bolt Beranek and Newman Inc. and the Xerox Palo Alto Research Center. Portable Standard Lisp (Hearn 1969; Griss 1981) was a Lisp dialect designed to be easily portable between different machines. MacLisp spawned a number of subdialects, such as Franz Lisp, which was developed at the University of California at Berkeley, and Zetalisp (Moon 1981), which was based on a special-purpose processor designed at the MIT Artificial Intelligence Laboratory to run Lisp very efficiently. The Lisp dialect used in this book, called Scheme (Steele 1975), was invented in 1975 by Guy Lewis Steele Jr. and Gerald Jay Sussman of the MIT Artificial Intelligence Laboratory and later reimplemented for instructional use at MIT. Scheme became an IEEE standard in 1990 (IEEE 1990). The Common Lisp dialect (Steele 1982, Steele 1990) was developed by the Lisp community to combine features from the earlier Lisp dialects to make an industrial standard for Lisp. Common Lisp became an ANSI standard in 1994 (ANSI 1994).
2在 20 世纪 70 年代,最主要的两个 Lisp 方言是 MIT 的 MAC 项目中开发的 MacLisp(Moon 1978;Priman 1983),以及在 Bolt Beranek and Newman Inc. 和 Xerox Palo Alto Research Center 开发的 Interlisp(Teitelman 1974),那时主要的 Lisp 程序都是用它们写的。Portable Standard Lisp(Hearn 1969;Griss 1981)是另一种 Lisp 方言,其设计就是为能更容易地移植到不同的计算机上。MacLisp 又发展出一些子方言,例如加州大学伯克得分校开发的 Franz Lisp,还有 Zetalisp(Moon 1981),它基于 MIT 人工智能实验室设计的一种专用处理器,这一处理器可以非常高效地运行 Lisp。本书所用的 Lisp 方言称为 Scheme(Steele 1975),是 1975 年由 MIT 人工智能实验室的 Guy Lewis Steele Jr. 和 Gerald Jay Sussman 设计的,后来的 MIT 为了教学使用而重新实现。在 1990 年 Scheme 变成了 IEEE 标准(IEEE 1990)。Common Lisp 方言(Steele 1982,Steele 1990)是由 Lisp 社团综合了早前各种 Lisp 方言的特征而开发出来的,希望能做成 Lisp 的工业标准。Common Lisp 在 1994 年成为 ANSI 标准(ANSI 1994)。
3 One such special application was a breakthrough computation of scientific importance -- an integration of the motion of the Solar System that extended previous results by nearly two orders of magnitude, and demonstrated that the dynamics of the Solar System is chaotic. This computation was made possible by new integration algorithms, a special-purpose compiler, and a special-purpose computer all implemented with the aid of software tools written in Lisp (Abelson et al. 1992; Sussman and Wisdom 1992).
3这方面有一个应用是科学计算的重要突破——有关太阳系运动的整合,它将的结果提高了两个数量级,并显示出太阳系统动力学的混沌性。完成这一计算依靠了一种新的整合算法、一个特殊的编译器以及一台专用计算机,所有这些都是在用 Lisp 写的软件工具的帮助下实现的(Abelson et al. 1992;Sussman 和 Wisdom 1992)。