'⇡'
心智的行为,其中它对简单观念施加其力量,主要有以下三种:1. 将几个简单观念结合成一个复合观念,从而形成所有复杂观念。2. 第二种是将两个观念,无论是简单的还是复杂的,放在一起,并并排展示,以便一次性观察它们,而不将它们合并为一个,这样它就获得了所有的关系观念。3. 第三种是将它们与在其真实存在中伴随的所有其他观念分开:这被称为抽象,因此形成了所有的普遍观念。
—约翰·洛克,《人类理解论》(1690)
我们即将研究 计算过程 的概念。计算过程是存在于计算机中的抽象存在。随着它们的发展,过程操纵其他称为 数据 的抽象事物。过程的演变由称为 程序 的规则模式指导。人们创建程序来指导过程。实际上,我们用我们的咒语召唤计算机的灵魂。
计算过程确实很像巫师对灵魂的想法。它无法被看见或触摸。它根本不由物质组成。然而,它非常真实。它可以进行智力工作。它可以回答问题。它可以通过在银行分配资金或通过控制工厂中的机器人手臂来影响世界。我们用来召唤过程的程序就像巫师的咒语。它们是由神秘和深奥的 编程语言 中的符号表达式精心构成的,这些表达式规定了我们希望我们的过程执行的任务。
在一台正常工作的计算机中,计算过程精确而准确地执行程序。因此,像魔法师的学徒一样,初学程序员必须学会理解和预见他们施法的后果。即使是程序中的小错误(通常称为 bugs 或 glitches)也可能产生复杂和意想不到的后果。
幸运的是,学习编程比学习魔法要安全得多,因为我们所处理的“灵魂”被方便地安全地控制着。然而,现实世界的编程需要谨慎、专业知识和智慧。例如,计算机辅助设计程序中的一个小错误可能导致飞机或大坝的灾难性崩溃,或者工业机器人自我毁灭。
高级软件工程师能够组织程序,以便他们可以合理地确信所产生的过程将执行预期的任务。他们能够提前可视化系统的行为。他们知道如何构建程序,以便意外问题不会导致灾难性后果,并且当问题出现时,他们可以 调试 他们的程序。设计良好的计算系统,就像设计良好的汽车或核反应堆一样,是以模块化的方式设计的,以便各个部分可以单独构建、替换和调试。
我们需要一种适合描述过程的语言,为此我们将使用编程语言 Lisp。正如我们日常的思维通常用我们的自然语言(如英语、法语或日语)表达,定量现象的描述则用数学符号表示,我们的过程性思维将用 Lisp 表达。Lisp 于 1950 年代末被发明,作为一种关于某些逻辑表达式(称为 递归方程)使用的推理形式,作为计算模型。该语言由约翰·麦卡锡(John McCarthy)构思,并基于他在“符号表达式的递归函数及其机器计算”一文中的内容(McCarthy 1960)。
尽管它起初作为一种数学形式主义,Lisp 是一种实用的编程语言。一个 Lisp 解释器 是一个执行用 Lisp 语言描述的过程的机器。第一个 Lisp 解释器是由麦卡锡在麻省理工学院电子研究实验室的人工智能小组和麻省理工学院计算中心的同事和学生的帮助下实现的。1 Lisp 的名称是 LISt Processing 的首字母缩写,旨在提供符号操作能力,以解决诸如代数表达式的符号微分和积分等编程问题。为此,它包括了新的数据对象,称为原子和列表,这使其与当时所有其他语言显著不同。
Lisp 并不是经过集中设计努力的产物。相反,它是在响应用户需求和务实的实现考虑下,以一种非正式的实验方式演变而来。Lisp 的非正式演变多年来一直在继续,Lisp 用户社区传统上抵制任何对语言进行“官方”定义的尝试。这种演变,加上最初构思的灵活性和优雅,使得 Lisp 能够不断适应现代程序设计的最新理念,成为今天广泛使用的第二古老的语言(只有 Fortran 更古老)。因此,Lisp 现在是一个方言家族,虽然共享大部分原始特征,但在重要方面可能彼此不同。本书中使用的 Lisp 方言称为 Scheme。2
由于其实验性质和对符号操作的强调,Lisp 起初在数值计算方面非常低效,至少与 Fortran 相比。然而,多年来,已经开发出将程序翻译成可以合理高效地执行数值计算的机器代码的 Lisp 编译器。对于特殊应用,Lisp 也被有效地使用。3 尽管 Lisp 还未克服其无可救药的低效的旧声誉,但现在在许多效率不是核心关注点的应用中使用 Lisp。例如,Lisp 已成为操作系统 shell 语言和编辑器及计算机辅助设计系统的扩展语言的首选语言。
如果 Lisp 不是一种主流语言,为什么我们要将其作为讨论编程的框架?因为该语言具有独特的特性,使其成为研究重要编程构造和数据结构的优秀媒介,并将它们与支持它们的语言特性联系起来。这些特性中最重要的是,Lisp 对过程的描述,称为 procedures,可以作为 Lisp 数据本身被表示和操作。这一点的重要性在于,有强大的程序设计技术依赖于模糊“被动”数据和“主动”过程之间的传统区别。正如我们将发现的,Lisp 在将过程作为数据处理方面的灵活性使其成为探索这些技术的最方便语言之一。将过程表示为数据的能力也使 Lisp 成为编写必须将其他程序作为数据进行操作的程序的优秀语言,例如支持计算机语言的解释器和编译器。除此之外,使用 Lisp 编程非常有趣。