灯下 登录
计算机科学 / SICP / subsection 中英对照

4.1.2 Representing Expressions

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)。

Racket #lang sicp
(cond ((> x 0) x)
 ((= x 0) (display 'zero) 0)
 (else (- x)))
Racket #lang sicp
(if (> x 0)
 x
 (if (= x 0)
 (begin (display 'zero) 0)
 (- x)))
Racket #lang sicp
(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))))))