

# 《计算机程序的结构与解释》序言，1996 年& 1984 年

## 《SICP》1996 年第二版序言

> 有没有可能软件不像其他任何东西，它注定要被抛弃:它的全部意义在于总是把它看成一个肥皂泡？
> 
> ——艾伦·J·佩利

自 1980 年以来，本书中的材料一直是麻省理工学院入门级计算机科学学科的基础。当第一版出版时，我们已经教了四年这种材料，直到第二版的出现，又过了十二年。我们感到高兴的是，我们的工作已被广泛采纳并纳入其他案文。我们已经看到我们的学生接受了这本书里的思想和程序，并把它们作为新的计算机系统和语言的核心。从字面上理解一句古老的犹太法典双关语，我们的学生已经成为我们的建设者。我们很幸运有这样有能力的学生和这样有成就的建设者。

在准备这个版本的过程中，我们结合了我们自己的教学经验以及麻省理工学院和其他地方的同事们的评论所提出的数百个澄清。我们已经重新设计了书中大多数主要的编程系统，包括通用算术系统、解释器、寄存器机器模拟器和编译器；我们重写了所有的程序示例，以确保任何符合 IEEE Scheme 标准(IEEE 1990)的 Scheme 实现都能够运行代码。

这个版本强调了几个新的主题。其中最重要的是在计算模型中处理时间的不同方法所扮演的中心角色:带状态的对象、并发编程、函数式编程、惰性求值和非确定性编程。我们包括了关于并发性和非确定性的新章节，并且我们试图在整本书中整合这个主题。

这本书的第一版严格遵循了我们麻省理工学院一学期的课程大纲。有了第二版中的所有新材料，不可能在一个学期内涵盖所有内容，所以教师必须进行挑选。在我们自己的教学中，我们有时会跳过关于逻辑编程的部分(4.4 节)，我们让学生使用寄存器机器模拟器，但我们不涉及它的实现(5.2 节)，我们只给出编译器的粗略概述(5.5 节)。即便如此，这仍然是一门紧张的课程。一些教师可能希望只讲述前三或四章，而将其他材料留给后续课程。

麻省理工学院出版社的万维网网站为这本书的用户提供支持。这包括书中的程序、示例编程作业、补充材料和 Lisp Scheme 方言的可下载实现。

—哈罗德·艾贝尔森和杰拉德·让伊·萨斯曼

## 《SICP》1984 年第一版序言

> 电脑就像小提琴。你可以想象一个新手先试留声机，再试小提琴。他说，后者听起来很可怕。这是我们从人文主义者和大多数计算机科学家那里听到的观点。他们说，对于特定的目的来说，计算机程序是好的，但是它们不灵活。小提琴和打字机都不是，除非你学会如何使用它们。
> 
> ——马文·明斯基，“为什么编程是表达理解不佳、表述不严谨的想法的好媒介”

“计算机程序的结构和解释”是麻省理工学院计算机科学的入门课程。这是麻省理工学院所有电子工程或计算机科学专业学生的必修课，占“公共核心课程”的四分之一，其中还包括两个关于电路和线性系统的科目以及一个关于数字系统设计的科目。自 1978 年以来，我们一直参与这一学科的发展，自 1980 年秋季以来，我们每年向 600 至 700 名学生教授这一材料的现有形式。这些学生中的大部分以前很少或没有接受过正式的计算培训，尽管许多人玩过一点计算机，少数人有丰富的编程或硬件设计经验。

我们对这个计算机科学导论课程的设计反映了两个主要问题。首先，我们想确立这样一种观念，即计算机语言不仅仅是让计算机执行操作的一种方式，而是一种表达方法论思想的新颖的形式媒介。因此，程序必须是写给人们阅读的，并且只是附带地给机器执行的。第二，我们认为，这个层次的主题要解决的基本材料不是特定编程语言结构的语法，也不是有效计算特定函数的聪明算法，甚至也不是算法的数学分析和计算的基础，而是用于控制大型软件系统的智能复杂性的技术。

我们的目标是，完成这门课程的学生应该对风格元素和编程美学有很好的感觉。他们应该掌握控制大型系统复杂性的主要技术。他们应该能够阅读 50 页长的程序，如果它是以一种典型的风格写的话。他们应该知道什么不该读，什么不需要在任何时候理解。他们应该对修改程序感到安全，保留原作者的精神和风格。

这些技能绝不是计算机编程所独有的。我们教授和借鉴的技术在所有工程设计中都是通用的。我们通过构建适当隐藏细节的抽象来控制复杂性。我们通过建立常规接口来控制复杂性，这些接口使我们能够通过以“混合和匹配”的方式组合标准的、众所周知的部分来构建系统。我们通过建立描述设计的新语言来控制复杂性，每种语言都强调设计的特定方面，而不强调其他方面。

我们对待这个问题的基本态度是，我们坚信“计算机科学”不是一门科学，它的重要性与计算机没有什么关系。计算机革命是我们思考方式和表达方式的革命。这一变化的本质是出现了所谓的过程认识论——从命令的角度研究知识结构，这与经典数学学科采取的更具陈述性的观点相反。数学为精确处理“是什么”的概念提供了一个框架计算为精确处理“如何做”的概念提供了一个框架

在教授我们的材料时，我们使用编程语言 Lisp 的一种方言。我们从不正式教授这门语言，因为我们不需要。我们就是用，过几天学生就拿起来了。这是类 Lisp 语言的一个很大的优势:它们很少有形成复合表达式的方法，而且几乎没有句法结构。所有的形式属性都可以在一个小时内完成，比如国际象棋的规则。过了一会儿，我们就忘记了语言的语法细节(因为根本没有),开始处理真正的问题——弄清楚我们想要计算什么，我们如何将问题分解成可管理的部分，以及我们将如何处理这些部分。Lisp 的另一个优点是，它比我们所知的任何其他语言都支持(但不强制)更多的程序模块化分解的大规模策略。我们可以进行过程和数据抽象，我们可以使用高阶函数来捕捉常见的使用模式，我们可以使用赋值和数据突变来模拟本地状态，我们可以用流和延迟评估来链接程序的各个部分，我们还可以轻松地实现嵌入式语言。所有这些都嵌入到一个交互式环境中，对增量程序设计、构建、测试和调试提供了出色的支持。我们感谢从约翰·麦卡锡开始的所有一代 Lisp 奇才，他们创造了一个前所未有的强大而优雅的工具。

Scheme 是我们使用的 Lisp 方言，它试图将 Lisp 和 Algol 的强大和优雅结合在一起。从 Lisp 中，我们获得了源自简单语法的元语言能力，程序作为数据对象的统一表示，以及垃圾收集堆分配的数据。从 Algol 中，我们得到了词法范围和块结构，这是 Algol 委员会中编程语言设计先驱们的礼物。我们希望引用约翰·雷诺兹和彼得·兰丁对 Church 的 lambda 演算与编程语言结构之间关系的见解。我们也认识到我们对数学家的亏欠，他们在计算机出现的几十年前就探索了这个领域。这些先驱包括阿隆佐·邱奇、巴克利·罗瑟、斯蒂芬·克莱尼和哈斯克尔·库里。

——哈罗德·艾贝尔森和杰拉德·让伊·萨斯曼