The evaluator is reminiscent of the symbolic differentiation program discussed
in 2.3.2. Both programs operate on symbolic expressions. In
both programs, the result of operating on a compound expression is determined
by operating recursively on the pieces of the expression and combining the
results in a way that depends on the type of the expression. In both programs
we used data abstraction to decouple the general rules of operation from the
details of how expressions are represented. In the differentiation program
this meant that the same differentiation procedure could deal with algebraic
expressions in prefix form, in infix form, or in some other form. For the
evaluator, this means that the syntax of the language being evaluated is
determined solely by the procedures that classify and extract pieces of
expressions.
Here is the specification of the syntax of our language:
这个求值器与 2.3.2 节讨论的符号求导程序颇为相似。两个程序都对符号表达式进行操作。在这两个程序中,对一个复合表达式进行操作的结果,是通过对表达式的各个组成部分递归地施加该操作,再根据表达式的类型将各部分结果组合起来而得到的。两个程序都借助数据抽象,将操作的一般规则与表达式的具体表示方式解耦。在求导程序中,这意味着同一个求导过程可以处理前缀形式、中缀形式或其他任何形式的代数表达式。对于求值器而言,这意味着被求值语言的语法完全由对表达式进行分类和提取成分的那些过程来决定。以下是我们语言的语法规范:
The only self-evaluating items are numbers and strings:
唯一自求值 (self-evaluating) 的对象是数和字符串:
(define (self-evaluating? exp)
(cond ((number? exp) true)
((string? exp) true)
(else false)))
Variables are represented by symbols:
变量由符号表示:
(define (variable? exp) (symbol? exp))
Quotations have the form (quote ⟨text-of-quotation⟩):
引用 (quotation) 的形式为 `(quote ⟨text-of-quotation⟩)`:
(define (quoted? exp)
(tagged-list? exp 'quote))
(define (text-of-quotation exp)
(cadr exp))
Quoted? is defined in terms of the procedure tagged-list?, which
identifies lists beginning with a designated symbol:
`quoted?` 是借助过程 `tagged-list?` 来定义的,后者用于识别以某个指定符号开头的表:
(define (tagged-list? exp tag)
(if (pair? exp)
(eq? (car exp) tag)
false))
Assignments have the form (set! ⟨var⟩ ⟨value⟩):
赋值的形式为 `(set! ⟨var⟩ ⟨value⟩)`:
(define (assignment? exp)
(tagged-list? exp 'set!))
(define (assignment-variable exp)
(cadr exp))
(define (assignment-value exp) (caddr exp))
Definitions have the form
定义的形式为
(define ⟨var⟩ ⟨value⟩)
or the form
或者为
(define (⟨var⟩ ⟨param₁⟩ … ⟨paramₙ⟩)
⟨body⟩)
The latter form (standard procedure definition) is syntactic sugar for
后一种形式(标准的过程定义)是以下写法的语法糖 (syntactic sugar):
(define ⟨var⟩
(lambda (⟨param₁⟩ … ⟨paramₙ⟩)
⟨body⟩))
The corresponding syntax procedures are the following:
与之对应的语法过程如下:
(define (definition? exp)
(tagged-list? exp 'define))
(define (definition-variable exp)
(if (symbol? (cadr exp))
(cadr exp)
(caadr exp)))
(define (definition-value exp)
(if (symbol? (cadr exp))
(caddr exp)
(make-lambda
(cdadr exp) ; formal parameters
(cddr exp)))) ; body
Lambda expressions are lists that begin with the symbol lambda:
lambda 表达式是以符号 `lambda` 开头的表:
(define (lambda? exp)
(tagged-list? exp 'lambda))
(define (lambda-parameters exp) (cadr exp))
(define (lambda-body exp) (cddr exp))
We also provide a constructor for lambda expressions, which is used by
definition-value, above:
我们还为 lambda 表达式提供了一个构造函数,供上面的 `definition-value` 使用:
(define (make-lambda parameters body)
(cons 'lambda (cons parameters body)))
Conditionals begin with if and have a predicate, a consequent, and an
(optional) alternative. If the expression has no alternative part, we provide
false as the alternative.
条件式以 `if` 开头,包含一个谓词、一个后件,以及一个可选的替代件。若表达式没有替代件部分,我们以 `false` 作为替代件。
(define (if? exp) (tagged-list? exp 'if))
(define (if-predicate exp) (cadr exp))
(define (if-consequent exp) (caddr exp))
(define (if-alternative exp)
(if (not (null? (cdddr exp)))
(cadddr exp)
'false))
We also provide a constructor for if expressions, to be used by
cond->if to transform cond expressions into if
expressions:
我们还为 `if` 表达式提供了一个构造函数,供 `cond->if` 将 `cond` 表达式变换为 `if` 表达式时使用:
(define (make-if predicate
consequent
alternative)
(list 'if
predicate
consequent
alternative))
Begin packages a sequence of expressions into a single expression. We
include syntax operations on begin expressions to extract the actual
sequence from the begin expression, as well as selectors that return the
first expression and the rest of the expressions in the
sequence.
`begin` 将一个表达式序列封装成单个表达式。我们提供了针对 `begin` 表达式的语法操作,用于从中提取实际的表达式序列,以及用于返回序列中第一个表达式和其余表达式的选择函数。
(define (begin? exp)
(tagged-list? exp 'begin))
(define (begin-actions exp) (cdr exp))
(define (last-exp? seq) (null? (cdr seq)))
(define (first-exp seq) (car seq))
(define (rest-exps seq) (cdr seq))
We also include a constructor sequence->exp (for use by cond->if)
that transforms a sequence into a single expression, using begin if
necessary:
我们还提供了一个构造函数 `sequence->exp`(供 `cond->if` 使用),它将一个表达式序列转换为单个表达式,必要时使用 `begin`:
(define (sequence->exp seq)
(cond ((null? seq) seq)
((last-exp? seq) (first-exp seq))
(else (make-begin seq))))
(define (make-begin seq) (cons 'begin seq))
A procedure application is any compound expression that is not one of the above
expression types. The car of the expression is the operator, and the
cdr is the list of operands:
过程应用 (procedure application) 是任何不属于上述表达式类型的复合表达式。表达式的 car 是运算符,cdr 是运算对象的表:
(define (application? exp) (pair? exp))
(define (operator exp) (car exp))
(define (operands exp) (cdr exp))
(define (no-operands? ops) (null? ops))
(define (first-operand ops) (car ops))
(define (rest-operands ops) (cdr ops))
Subheading: Derived expressions
Some special forms in our language can be defined in terms of expressions
involving other special forms, rather than being implemented directly. One
example is cond, which can be implemented as a nest of if
expressions. For example, we can reduce the problem of evaluating the
expression
我们语言中的某些特殊形式,可以用涉及其他特殊形式的表达式来定义,而无需直接实现。cond 就是一个例子——它可以实现为一组嵌套的 if 表达式。例如,对表达式求值的问题,
to the problem of evaluating the following expression involving if and
begin expressions:
可以归约为对下面这个包含 if 和 begin 表达式的表达式求值:
Implementing the evaluation of cond in this way simplifies the evaluator
because it reduces the number of special forms for which the evaluation process
must be explicitly specified.
以这种方式实现 cond 的求值,能够简化求值器,因为它减少了求值过程必须显式规定的特殊形式的数量。
We include syntax procedures that extract the parts of a cond
expression, and a procedure cond->if that transforms cond
expressions into if expressions. A case analysis begins with
cond and has a list of predicate-action clauses. A clause is an
else clause if its predicate is the symbol else.
我们提供用于提取 cond 表达式各部分的语法过程,以及将 cond 表达式变换为 if 表达式的过程 cond->if。一个情况分析以 cond 开头,并带有一组谓词-动作子句的表。如果某个子句的谓词是符号 else,则该子句为 else 子句。
Expressions (such as cond) that we choose to implement as syntactic
transformations are called
derived expressions. Let
expressions are also derived expressions (see
Exercise 4.6).
我们选择以句法变换方式实现的表达式(如 cond)称为派生表达式 (derived expressions)。let 表达式也是派生表达式(见练习 4.6)。
(cond ((> x 0) x)
((= x 0) (display 'zero) 0)
(else (- x))) (if (> x 0)
x
(if (= x 0)
(begin (display 'zero) 0)
(- x))) (define (cond? exp)
(tagged-list? exp 'cond))
(define (cond-clauses exp) (cdr exp))
(define (cond-else-clause? clause)
(eq? (cond-predicate clause) 'else))
(define (cond-predicate clause)
(car clause))
(define (cond-actions clause)
(cdr clause))
(define (cond->if exp)
(expand-clauses (cond-clauses exp)))
(define (expand-clauses clauses)
(if (null? clauses)
'false ; no else clause
(let ((first (car clauses))
(rest (cdr clauses)))
(if (cond-else-clause? first)
(if (null? rest)
(sequence->exp
(cond-actions first))
(error "ELSE clause isn't
last: COND->IF"
clauses))
(make-if (cond-predicate first)
(sequence->exp
(cond-actions first))
(expand-clauses
rest))))))