When we introduced the substitution model in 1.1.5 we showed how
the combination (f 5) evaluates to 136, given the following procedure
definitions:
在 1.1.5 节引入代换模型时,我们展示了在以下过程定义下,组合式 `(f 5)` 如何求值为 136:
We can analyze the same example using the environment model. Figure 3.4
shows the three procedure objects created by evaluating the definitions of
f, square, and sum-of-squares in the global environment.
Each procedure object consists of some code, together with a pointer to the
global environment.
Figure 3.4: Procedure objects in the global frame.
现在我们可以用环境模型分析同一个例子。图 3.4 展示了在全局环境中对 `f`、`square` 和 `sum-of-squares` 的定义求值后所创建的三个过程对象。每个过程对象都由若干代码以及指向全局环境的指针组成。
图 3.4:全局框架中的过程对象。
In Figure 3.5 we see the environment structure created by evaluating the
expression (f 5). The call to f creates a new environment E1
beginning with a frame in which a, the formal parameter of f, is
bound to the argument 5. In E1, we evaluate the body of f:
图 3.5 展示了对表达式 `(f 5)` 求值时所创建的环境结构。对 `f` 的调用创建了一个新环境 E1,它以一个框架开始,`f` 的形参 `a` 在其中被绑定到实参 `5`。在 E1 中,我们对 `f` 的过程体求值:
Figure 3.5: Environments created by evaluating (f 5) using the procedures in Figure 3.4.
图 3.5:使用图 3.4 中的过程对 `(f 5)` 求值时所创建的各个环境。
To evaluate this combination, we first evaluate the subexpressions. The first
subexpression, sum-of-squares, has a value that is a procedure object.
(Notice how this value is found: We first look in the first frame of E1, which
contains no binding for sum-of-squares. Then we proceed to the
enclosing environment, i.e. the global environment, and find the binding shown
in Figure 3.4.) The other two subexpressions are evaluated by applying
the primitive operations + and * to evaluate the two combinations
(+ a 1) and (* a 2) to obtain 6 and 10, respectively.
为了对这个组合式求值,我们首先对各子表达式求值。第一个子表达式 `sum-of-squares` 的值是一个过程对象。(注意这个值是如何找到的:我们首先查看 E1 的第一个框架,其中没有 `sum-of-squares` 的绑定;然后转向外围环境,即全局环境,并找到图 3.4 所示的绑定。)对另外两个子表达式的求值,则是将基本操作 `+` 和 `*` 应用于子组合式 `(+ a 1)` 和 `(* a 2)`,分别得到 6 和 10。
Now we apply the procedure object sum-of-squares to the arguments 6 and
10. This results in a new environment E2 in which the formal parameters
x and y are bound to the arguments. Within E2 we evaluate the
combination (+ (square x) (square y)). This leads us to evaluate
(square x), where square is found in the global frame and
x is 6. Once again, we set up a new environment, E3, in which x
is bound to 6, and within this we evaluate the body of square, which is
(* x x). Also as part of applying sum-of-squares, we must
evaluate the subexpression (square y), where y is 10. This
second call to square creates another environment, E4, in which
x, the formal parameter of square, is bound to 10. And within E4
we must evaluate (* x x).
现在我们将过程对象 `sum-of-squares` 应用于实参 6 和 10。这产生了一个新环境 E2,其中形参 `x` 和 `y` 被绑定到对应的实参。在 E2 中,我们对组合式 `(+ (square x) (square y))` 求值。这引导我们对 `(square x)` 求值,其中 `square` 在全局框架中找到,`x` 为 6。我们再次建立一个新环境 E3,其中 `x` 被绑定到 6,并在其中对 `square` 的过程体 `(* x x)` 求值。同样作为 `sum-of-squares` 应用的一部分,我们还必须对子表达式 `(square y)` 求值,其中 `y` 为 10。对 `square` 的第二次调用又创建了另一个环境 E4,其中 `square` 的形参 `x` 被绑定到 10,在 E4 中我们对 `(* x x)` 求值。
The important point to observe is that each call to square creates a new
environment containing a binding for x. We can see here how the
different frames serve to keep separate the different local variables all named
x. Notice that each frame created by square points to the global
environment, since this is the environment indicated by the square
procedure object.
这里值得注意的重要一点是,每次调用 `square` 都会创建一个包含 `x` 绑定的新环境。由此可以看出,不同的框架如何将所有名为 `x` 的不同局部变量相互隔离。注意,每个由 `square` 创建的框架都指向全局环境,因为这正是 `square` 过程对象所指示的环境。
After the subexpressions are evaluated, the results are returned. The values
generated by the two calls to square are added by sum-of-squares,
and this result is returned by f. Since our focus here is on the
environment structures, we will not dwell on how these returned values are
passed from call to call; however, this is also an important aspect of the
evaluation process, and we will return to it in detail in Chapter 5.
各子表达式求值完毕后,结果被返回。两次调用 `square` 所产生的值由 `sum-of-squares` 相加,该结果再由 `f` 返回。由于我们这里关注的是环境结构,不会深入探讨这些返回值在调用之间如何传递;然而,这也是求值过程的一个重要方面,我们将在第 5 章中详细回到这个话题。
(define (square x)
(* x x))
(define (sum-of-squares x y)
(+ (square x) (square y)))
(define (f a)
(sum-of-squares (+ a 1) (* a 2))) (sum-of-squares (+ a 1) (* a 2))