# 4元语言抽象

> 译者： [https://sicp.comp.nus.edu.sg/chapters/72](https://sicp.comp.nus.edu.sg/chapters/72)

 <chapter>> …换句话说，魔术是Abracadabra，芝麻芝麻酱（Open Sesame）和其他魔术，但是一个故事中的魔术词在下一故事中并不是魔术。 真正的魔力在于了解哪些单词有效，何时，何地起作用； 诀窍是学习技巧。
> 
> ……这些词是由我们字母表中的字母组成的：我们可以用笔画出几对花体。 这是关键！ 如果我们只能动手，那宝藏也是！ 好像— _的钥匙就是_的宝藏一样！
> 
> John BarthChimera

<chaptercontent></chaptercontent>

在我们对程序设计的研究中，我们已经看到，专家程序员使用所有复杂系统的设计师所使用的通用技术来控制其设计的复杂性。 它们组合原始元素以形成复合对象，将复合对象抽象以形成更高级别的构建块，并且通过采用适当的系统结构的大规模视图来保留模块化。 在说明这些技术时，我们使用JavaScript作为一种语言来描述过程，并构造计算数据对象和过程以对现实世界中的复杂现象建模。 但是，当我们面对日益复杂的问题时，我们会发现JavaScript或实际上任何固定的编程语言不足以满足我们的需求。 我们必须不断求助于新的语言，以便更有效地表达我们的想法。 建立新的语言是控制工程设计复杂性的强大策略。 我们通常可以通过采用一种新的语言来增强我们处理复杂问题的能力，该语言使我们能够使用不同的方式（特别是使用原语，组合方式和抽象方式）来描述（并思考）问题。 非常适合眼前的问题。 [[1]](72#footnote-1)

编程拥有多种语言。 有物理语言，例如特定计算机的机器语言。 这些语言在存储和原始机器指令的各个位方面涉及数据和控制的表示。 机器语言程序员关心的是使用给定的硬件来架设系统和实用程序，以有效实施资源受限的计算。 在机器语言基板上竖立的高级语言掩盖了有关将数据表示为位集合以及将程序表示为原始指令序列的担忧。 这些语言具有适合大型系统组织的组合和抽象方法，例如函数定义。

_元语言抽象_（建立新语言）在工程设计的所有分支中都发挥着重要作用。 这对计算机编程特别重要，因为在编程中，我们不仅可以制定新的语言，而且可以通过构造评估器来实现这些语言。 用于编程语言的_评估程序_（或_解释程序_）是一种功能，当应用于该语言的表达式时，它将执行评估该表达式所需的动作。

毫不夸张地说，这是编程中最基本的想法：

> 确定程序语言中语句和表达式含义的评估程序只是另一个程序。

To appreciate this point is to change our images of ourselves as programmers. We come to see ourselves as designers of languages, rather than only users of languages designed by others.

实际上，我们几乎可以将任何程序视为某种语言的评估器。 例如， [2.5.3](46)[3.3.4](61)[3.3.5](62) 部分的约束传播器是合法的语言 ，每个都有自己的基元，组合方式和抽象方式。 从这个角度看，应付大型计算机系统的技术与构建新计算机语言的技术融合在一起，计算机科学本身变得（而且不少于）构建适当的描述性语言的学科。

现在，我们开始对以其他语言来建立语言的技术进行浏览。 在本章中，我们将以JavaScript为基础，将评估器实现为JavaScript函数。 JavaScript特别适合此任务，因为它具有表示和操纵符号表达式的能力。 我们将通过构建JavaScript本身的评估程序来迈出第一步，以了解如何实现语言。 我们的评估人员实施的语言将是JavaScript的子集。 尽管本章中描述的评估程序是为JavaScript的特定子集编写的，但它包含任何设计用于编写顺序机器程序的面向表达式的语言的评估程序的基本结构。 （实际上，大多数语言处理器在其内部都包含一个小的评估器。）为说明和讨论目的简化了评估器，并且省略了一些功能，这些功能对于包含在生产质量的JavaScript中非常重要。 系统。 不过，这个简单的评估器足以执行本书中的大多数程序。 [[2]](72#footnote-2)

使评估程序可作为JavaScript程序访问的一个重要优点是，我们可以通过将替代规则描述为对评估程序的修改来实现替代评估规则。 我们可以充分利用此功能的一个地方是，对计算模型体现时间概念的方式进行额外控制，这在第3章的讨论中至关重要。在那里，我们减轻了状态的某些复杂性 通过使用流将世界中时间的表示与计算机中的时间解耦来进行分配。 但是，我们的流程序有时很麻烦，因为它们受到JavaScript的应用顺序评估的约束。 在 [4.2](81) 部分中，我们将通过修改评估程序以提供_正常顺序评估_来更改基础语言，以提供更优雅的方法。

<chaptercontent></chaptercontent>

* * *

[[1]](72#footnote-link-1) The same idea is pervasive throughout all of engineering. For example, electrical engineers use many different languages for describing circuits. Two of these are the language of electrical _networks_ and the language of electrical _systems_. The network language emphasizes the physical modeling of devices in terms of discrete electrical elements. The primitive objects of the network language are primitive electrical components such as resistors, capacitors, inductors, and transistors, which are characterized in terms of physical variables called voltage and current. When describing circuits in the network language, the engineer is concerned with the physical characteristics of a design. In contrast, the primitive objects of the system language are signal-processing modules such as filters and amplifiers. Only the functional behavior of the modules is relevant, and signals are manipulated without concern for their physical realization as voltages and currents. The system language is erected on the network language, in the sense that the elements of signal-processing systems are constructed from electrical networks. Here, however, the concerns are with the large-scale organization of electrical devices to solve a given application problem; the physical feasibility of the parts is assumed. This layered collection of languages is another example of the stratified design technique illustrated by the picture language of section <ref name="sec:graphics">[2.2.4](33)</ref>.

[[2]](72#footnote-link-2) The most important features that our evaluator leaves out are mechanisms for handling errors and supporting debugging. For a more extensive discussion of evaluators, see Friedman, Wand, and Haynes 1992, which gives an exposition of programming languages that proceeds via a sequence of evaluators written in the Scheme dialect of Lisp.

</chapter>