评估顺序,SICP 练习

Mat*_*eré 4 scheme sicp mit-scheme

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

练习 4.1。请注意,我们无法判断元循环求值器是从左到右还是从右到左计算操作数。它的求值顺序是从底层 Lisp 继承而来的:如果值列表中 cons 的参数是从左到右求值的,那么值列表将从左到右求值;如果 cons 的参数是从右到左计算的,那么值列表将从右到左计算操作数。编写一个从左到右计算操作数的值列表版本,而不管底层 Lisp 中的计算顺序如何。还要编写一个从右到左计算操作数的值列表版本。

原来的功能是

(define (list-of-values exps env)
  (if (no-operands? exps)
      '()
      (cons (eval (first-operand exps) env)
            (list-of-values (rest-operands exps) env))))
Run Code Online (Sandbox Code Playgroud)

我的解决方案如下:

;;; 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))
Run Code Online (Sandbox Code Playgroud)

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

Wor*_*lux 5

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))))
Run Code Online (Sandbox Code Playgroud)

因为 scheme 在它的评估中急切,所以(eval (first-operand exps) env)总是在应用函数之前评估它。