|
计算机就像小提琴。你可以想象一个新手先试留声机,再试小提琴。他说,后者听起来糟透了。这就是我们从人文学者和大多数计算机科学家那里听到的论点。他们说,计算机程序对特定目的有好处,但它们不灵活。小提琴也是,打字机也是,直到你学会如何使用它。
Marvin Minsky,〈为什么编程是表达
|
《计算机程序的构造和解释》是麻省理工学院计算机科学的入门课程。它是 MIT 所有电气工程或计算机科学专业学生的必修课,占"公共核心课程"的四分之一,该核心课程还包括两门电路与线性系统课程和一门数字系统设计课程。我们自 1978 年以来一直参与该课程的发展,自 1980 年秋季以来一直以目前的形式教授这些内容,每年有 600 到 700 名学生。这些学生大多之前几乎没有接受过正式的计算训练,尽管许多人玩过一些计算机,少数人有丰富的编程或硬件设计经验。
我们对这门计算机科学入门课程的设计反映了两个主要关切。第一,我们希望建立这样一种观念:计算机语言不僅仅是让计算机执行操作的方式,更是一种表达方法论思想的新型形式媒介。因此,程序必须是为了供人阅读而编写,顺便为了机器执行。第二,我们认为,这门层次课程所要涉及的核心内容不是特定编程语言构造的语法,不是高效计算特定函数的巧妙算法,甚至不是算法的数学分析和计算基础,而是用于控制大型软件系统智力复杂度的技术。
我们的目标是,完成这门课程的学生应该对编程的风格要素和美学有良好的感受。他们应该掌握控制大型系统复杂性的主要技术。他们应该能够阅读长达 50 页的程序——如果它是以示范性的风格编写的。他们应该知道什么不该读,以及在任何时刻他们不需要理解什么。他们应该在修改程序时感到有把握,保留原作者的精神和风格。
这些技能絕非计算机编程独有。我们教授和借鉴的技术是所有工程设计共通的。我们通过构建合适的抽象来隐藏细节,从而控制复杂性。我们通过建立约定接口来组装标准、充分理解的部件,以"混合搭配"的方式构建系统,从而控制复杂性。我们通过建立描述设计的新语言来控制复杂性,每种语言强调设计的某些方面并弱化其他方面。
我们处理这门课程的方法基于这样一个信念:"计算机科学"不是一门科学,它的意义与计算机关系不大。计算机革命是一场关于我们思考方式和表达思想方式的革命。这种变化的本质是出现了一种最好称为程序性认识论的东西——从命令式视角研究知识的结构,与经典数学学科采取的更偏向声明式的视角形成对比。数学提供了一个精确处理"是什么"概念的框架。计算则提供了一个精确处理"怎样做"概念的框架。
在教授我们的材料时,我们使用 Lisp 编程语言的一种方言。我们从不正式教授这种语言,因为我们不需要。我们只是使用它,学生在几天内就能掌握。这是类 Lisp 语言的一大优势:它们形成复合表达式的方式非常少,几乎没有语法结构。所有的形式化属性可以在一小时内讲完,就像国际象棋的规则一样。很快我们就忘记了语言的语法细节(因为根本没有),转而处理真正的问题——弄清楚我们想要计算什么,如何将问题分解为可管理的部分,以及如何处理这些部分。Lisp 的另一个优势是,它支持(但不强制)比我们知道的任何其他语言都更多的大型程序模块分解策略。我们可以进行过程抽象和数据抽象,可以使用高阶函数来捕获常见的使用模式,可以使用赋值和数据修改来建模局部状态,可以用流和延迟求值来连接程序的各个部分,还可以轻松实现嵌入式语言。所有这些都嵌入在一个交互式环境中,对增量式程序设计、构建、测试和调试提供了出色的支持。我们感谢从 John McCarthy 开始的历代 Lisp 魔术师,他们打造了一个具有空前力量和优雅的精致工具。
Scheme,我们使用的 Lisp 方言,试图将 Lisp 和 Algol 的力量与优雅结合起来。从 Lisp 中,我们获得了源于简单语法、程序作为数据对象的统一表示以及垃圾回收的堆分配数据的元语言能力。从 Algol 中,我们获得了词法作用域和块结构,这是 Algol 委员会中编程语言设计先驱们的馈赠。我们要感谢 John Reynolds 和 Peter Landin 对 Church 的 lambda 演算与编程语言结构之间关系的洞察。我们也要感谢在计算机出现之前几十年就已探索这片领域的数学家们。这些先驱包括 Alonzo Church、Barkley Rosser、Stephen Kleene 和 Haskell Curry。