评估顺序,SICP练习

Order of evaluation, SICP exercise

所以,我正在努力完成 SICP。 第4章的第一个练习是:

Exercise 4.1. Notice that we cannot tell whether the metacircular evaluator evaluates operands from left to right or from right to left. Its evaluation order is inherited from the underlying Lisp: If the arguments to cons in list-of-values are evaluated from left to right, then list-of-values will evaluate operands from left to right; and if the arguments to cons are evaluated from right to left, then list-of-values will evaluate operands from right to left. Write a version of list-of-values that evaluates operands from left to right regardless of the order of evaluation in the underlying Lisp. Also write a version oflist-of-values that evaluates operands from right to left.

原函数为

(define (list-of-values exps env)
  (if (no-operands? exps)
      '()
      (cons (eval (first-operand exps) env)
            (list-of-values (rest-operands exps) env))))

我的解决方案如下:

;;; left-to-right
(define (list-of-values-l2r exps env)
  (if (no-operands? exps)
      '()
      (let ((first-exp (eval (first-operand exps) env)))
        (cons first-exp
              (list-of-values-l2r (rest-operands exps) env)))))

;;; right-to-left
(define (list-of-values-r2l exps env)
  (list-of-values-l2r (reverse exps) env))

但是,我不确定我的做法是否正确。我的直觉 是 let 语句强制执行 eval,有人可以确认吗?

let 只是语法糖,没有 let 的重写看起来像

(define (list-of-values-l2r exps env)
  (if (no-operands? exps)
      '()
      ((lambda (first-exp)
          (cons first-exp
                (list-of-values-l2r (rest-operands exps) env)))
        (eval (first-operand exps) env))))

因为方案急于求值,所以 (eval (first-operand exps) env) 总是在应用函数之前求值。