第一版序言
Preface to the First Edition
计算机就像小提琴一样。你可以想象一个新手先使用了留声机,然后再用小提琴。他会说后者的声音听起来很恐怖。这正是我们听到的人文主义者和大部分计算机科学家之间的争论。他们说,计算机程序在特定用途下很好,但不够灵活。小提琴或者打字机也不够灵活,直到你学会如何使用它。
——马文·闵斯基,《为什么编程是表达难以理解且表述草率的想法的良好媒介》
A computer is like a violin. You can imagine a novice trying first a phonograph and then a violin. The latter, he says, sounds terrible. That is the argument we have heard from our humanists and most of our computer scientists. Computer programs are good, they say, for particular purposes, but they aren't flexible. Neither is a violin, or a typewriter, until you learn how to use it.
Marvin Minsky, ''Why Programming Is a Good Medium for Expressing Poorly-Understood and Sloppily-Formulated Ideas''
《计算机程序的构造和解释》是麻省理工学院在计算机科学领域的入门课程。对于所有主修电子工程和计算机科学的MIT学生来说,这门课不但是必修的,还是“公共核心课程”的四分之一,后者还包括两门关于电路和线性系统的课程,以及一门关于数字系统设计的课程。我们自1978年起就开始了这门课的开发。自1980年秋季开始,我们一直在以它们目前的形式向每年的6、700个学生教授这些内容。大部分学生先前都没有或仅接受了很少的关于计算的正式训练,尽管他们中的很多玩弄过计算机,一些人还有过大量的编程或硬件设计经验。
''The Structure and Interpretation of Computer Programs'' is the entry-level subject in computer science at the Massachusetts Institute of Technology. It is required of all students at MIT who major in electrical engineering or in computer science, as one-fourth of the ''common core curriculum,'' which also includes two subjects on circuits and linear systems and a subject on the design of digital systems. We have been involved in the development of this subject since 1978, and we have taught this material in its present form since the fall of 1980 to between 600 and 700 students each year. Most of these students have had little or no prior formal training in computation, although many have played with computers a bit and a few have had extensive programming or hardware-design experience.
我们对这门介绍性的计算机科学课程的设计反映了两个主要的考虑:首先,我们希望建立一种观念,即计算机语言不仅是一种让计算机执行操作的方式,更是一种表达对于方法的想法的新颖而正式的媒介。因此,程序必须是写给人读的,它们只是偶尔被用来让机器执行。其次,我们相信这个程度的课程能传达的核心内容不是特定编程语言构造的语法,不是能更高效地计算特定函数的聪明算法,也不是算法的数学分析和计算的基础,而是用于控制大型软件系统智力复杂度的技巧。
Our design of this introductory computer-science subject reflects two major concerns. First, we want to establish the idea that a computer language is not just a way of getting a computer to perform operations but rather that it is a novel formal medium for expressing ideas about methodology. Thus, programs must be written for people to read, and only incidentally for machines to execute. Second, we believe that the essential material to be addressed by a subject at this level is not the syntax of particular programming-language constructs, nor clever algorithms for computing particular functions efficiently, nor even the mathematical analysis of algorithms and the foundations of computing, but rather the techniques used to control the intellectual complexity of large software systems.
我们的目的是要让完成这门课的学生对编程风格和美学的要素具有良好的感觉。他们应该掌握控制大型系统复杂度的主要技巧。他们应该有能力阅读一段50页长的程序,只要它是以模范性风格编写的。他们应该知道哪些不用读,以及哪些他们永远不需要理解。他们应该对修改程序感到安心,并保留原作者的精神和风格。
Our goal is that students who complete this subject should have a good feel for the elements of style and the aesthetics of programming. They should have command of the major techniques for controlling complexity in a large system. They should be capable of reading a 50-page-long program, if it is written in an exemplary style. They should know what not to read, and what they need not understand at any moment. They should feel secure about modifying a program, retaining the spirit and style of the original author.
这些技巧绝不是计算机编程特有的。我们教授和利用的技巧是为所有工程设计所共通的。我们通过建立适时隐藏细节的抽象来控制复杂度;我们通过建立使我们得以通过混搭规范且容易理解的片段来构建系统的常规接口来控制复杂度;我们通过建立用以描述设计的、重视设计的特定方面而忽略其他方面的新语言来控制复杂度。
These skills are by no means unique to computer programming. The techniques we teach and draw upon are common to all of engineering design. We control complexity by building abstractions that hide details when appropriate. We control complexity by establishing conventional interfaces that enable us to construct systems by combining standard, well-understood pieces in a ''mix and match'' way. We control complexity by establishing new languages for describing a design, each of which emphasizes particular aspects of the design and deemphasizes others.
隐含在我们教授这门课的方式之下的,是我们认为“计算机科学”不是一门科学,而且它的重要性也和计算机没有很大关系的信念。计算机革命是我们思考方式和表达方式的革命。变化的本质是那个也许最好被称为程序化认知论的东西出现:通过祈使性的角度对知识结构进行研究,而不是经典数学课程采用的陈述性角度。数学为精确地处理“是什么”的想法提供框架,而计算为精确地处理“怎么做”的想法提供框架。
Underlying our approach to this subject is our conviction that ''computer science'' is not a science and that its significance has little to do with computers. The computer revolution is a revolution in the way we think and in the way we express what we think. The essence of this change is the emergence of what might best be called procedural epistemology -- the study of the structure of knowledge from an imperative point of view, as opposed to the more declarative point of view taken by classical mathematical subjects. Mathematics provides a framework for dealing precisely with notions of ''what is.'' Computation provides a framework for dealing precisely with notions of ''how to.''
在教授这些内容的过程中,我们使用了Lisp编程语言的一种方言。我们从不正式教授语言本身,因为没有这个必要。我们只是使用它,学生们也能在几天之内学会它。类Lisp语言有一个巨大的优点:它们只有很少几种组成复合表达式的方式,且几乎没有语法结构。所有的正式属性都可以在一个小时内说明完,就和国际象棋的规则一样。在一段时间后我们会忘记语言的语法细节(因为没有),并开始解决真正的问题:找出我们想要计算什么、如何把问题分解成可处理的小部分以及如何对这些部分开展工作。Lisp的另一个优点是它和其他任何语言相比都更支持(但从不强制)程序模块分解的大规模策略。我们可以使用过程和数据抽象,我们可以使用高阶函数来捕捉常见的使用模式,我们可以通过赋值和数据变异对本地状态进行建模,我们可以将程序的部分和流与延迟求值相连,我们还可以轻易地实现嵌入式语言。所有这些都被嵌入了一个提供卓越的增量式程序设计、构造、测试和调试支持的交互式环境中。我们感谢塑造了这种具有空前力量和优雅的工具的约翰·麦卡锡,以及他之后的一代代Lisp向导们。
In teaching our material we use a dialect of the programming language Lisp. We never formally teach the language, because we don't have to. We just use it, and students pick it up in a few days. This is one great advantage of Lisp-like languages: They have very few ways of forming compound expressions, and almost no syntactic structure. All of the formal properties can be covered in an hour, like the rules of chess. After a short time we forget about syntactic details of the language (because there are none) and get on with the real issues -- figuring out what we want to compute, how we will decompose problems into manageable parts, and how we will work on the parts. Another advantage of Lisp is that it supports (but does not enforce) more of the large-scale strategies for modular decomposition of programs than any other language we know. We can make procedural and data abstractions, we can use higher-order functions to capture common patterns of usage, we can model local state using assignment and data mutation, we can link parts of a program with streams and delayed evaluation, and we can easily implement embedded languages. All of this is embedded in an interactive environment with excellent support for incremental program design, construction, testing, and debugging. We thank all the generations of Lisp wizards, starting with John McCarthy, who have fashioned a fine tool of unprecedented power and elegance.
Scheme,我们使用的Lisp方言,是一次将Lisp和Algol的力量与优雅结合在一起的尝试。我们从Lisp中获取源自简单语法、将程序作为数据对象的统一表示和带有垃圾回收的堆分配数据的元语言的力量,再从Algol中获取Algol委员会中编程语言设计领域的先驱们赠予的词法作用域和块结构。我们想嘉奖约翰·雷诺兹和彼得·兰丁对于邱奇的λ演算和编程语言结构之间关系的洞见。我们还意识到应该感谢在计算机出现之前踏上这片领域的数学家们。这些先驱包括阿隆佐·邱奇、巴克里·罗瑟、斯蒂芬·克莱尼和哈斯凯尔·加里。
Scheme, the dialect of Lisp that we use, is an attempt to bring together the power and elegance of Lisp and Algol. From Lisp we take the metalinguistic power that derives from the simple syntax, the uniform representation of programs as data objects, and the garbage-collected heap-allocated data. From Algol we take lexical scoping and block structure, which are gifts from the pioneers of programming-language design who were on the Algol committee. We wish to cite John Reynolds and Peter Landin for their insights into the relationship of Church's lambda calculus to the structure of programming languages. We also recognize our debt to the mathematicians who scouted out this territory decades before computers appeared on the scene. These pioneers include Alonzo Church, Barkley Rosser, Stephen Kleene, and Haskell Curry.