灯下 登录
计算机科学 / SICP / 4.1.2 Representing Expressions

Exercise 4.7 · 习题

Exercise 4.7: Let* is similar to
let, except that the bindings of the let* variables are performed
sequentially from left to right, and each binding is made in an environment in
which all of the preceding bindings are visible. For example

(let* ((x 3)
(y (+ x 2))
(z (+ x y 5)))
(* x z))

returns 39. Explain how a let* expression can be rewritten as a set of
nested let expressions, and write a procedure let*->nested-lets
that performs this transformation. If we have already implemented let
(Exercise 4.6) and we want to extend the evaluator to handle let*,
is it sufficient to add a clause to eval whose action is

(eval (let*->nested-lets exp) env)

or must we explicitly expand let* in terms of non-derived expressions?

练习 4.7:let* 与 let 类似,但 let* 变量的绑定按从左到右的顺序依次进行,每个绑定都在前面所有绑定均可见的环境中建立。例如,

(let* ((x 3)
(y (+ x 2))
(z (+ x y 5)))
(* x z))

返回 39。请解释 let* 表达式如何改写为一组嵌套的 let 表达式,并编写执行此变换的过程 let*->nested-lets。若我们已经实现了 let(练习 4.6),现在想扩展求值器以处理 let*,在 eval 中添加如下子句

(eval (let*->nested-lets exp) env)

是否足够?还是必须将 let* 显式展开为非派生表达式?

Racket #lang sicp
(let* ((x 3)
 (y (+ x 2))
 (z (+ x y 5)))
 (* x z))
Racket #lang sicp
(eval (let*->nested-lets exp) env)