問題4.30 – SICP(計算機プログラムの構造と解釈)その204

問題4.30

並びの中の式の内、最後の式以外(途中の式)の引数は評価されず遅延される。
途中の式でも基本手続きの場合はその引数は評価される。

並び(元々のバージョン)

(define (eval-sequence exps env)
  (cond ((last-exp? exps) (eval (first-exp exps) env))
        (else (eval (first-exp exps) env)
              (eval-sequence (rest-exps exps) env))))

並び(Cy D. Fect バージョン)

(define (eval-sequence exps env)
  (cond ((last-exp? exps) (eval (first-exp exps) env))
        (else (actual-value (first-exp exps) env)
              (eval-sequence (rest-exps exps) env))))

a.

並びの中の式 (proc (car items)) は、((lambda (x) (newline) (display x)) (car items)) となり、基本手続きのためにその引数は評価されてゆき、結果が正しく表示されることになる。

(define (for-each proc items)
  (if (null? items)
      'done
      (begin (proc (car items))
             (for-each proc (cdr items)))))

(for-each (lambda (x) (newline) (display x))
          '(57 321 88))

実行結果

;;; L-Eval input:
(for-each (lambda (x) (newline) (display x))
          '(57 321 88))

57
321
88
;;; L-Eval value:
done

b.

(define (p1 x)
  (set! x (cons x '(2)))
  x)

(define (p2 x)
  (define (p e)
    e
    x)
  (p (set! x (cons x '(2)))))

元々の eval-sequence の場合

手続き p1 では並びの中の式が基本手続きのためにその引数は評価されてゆき、(set! x (cons x '(2))) も遅延することなく評価される。
手続き p2 では p は基本手続きではないために、その引数 (set! x (cons '(2))) は遅延されて評価されない。

;;; L-Eval input:
(p1 1)

;;; L-Eval value:
(1 2)

;;; L-Eval input:
(p2 1)

;;; L-Eval value:
1

Cy D. Fect の提案する eval-sequence の場合

手続き p1, p2 とも途中の式も強制されるため、どちらの (set! x (cons x '(2))) も評価される。

;;; L-Eval input:
(p1 1)

;;; L-Eval value:
(1 2)

;;; L-Eval input:
(p2 1)

;;; L-Eval value:
(1 2)

c.

a. の例では、途中の式に基本手続きを使用しているため遅延が行われない。
Cy D. Fect の eval-sequence では途中の式も強制するため遅延が行われない。

d.

パス

参考:SICP 4.2.2 Ex. 4.27 Ex. 4.28 Ex. 4.29 Ex. 4.30 Ex. 4.31 – nakayama-blog
   4.2.2 遅延評価の解釈系 – 三十路プログラマ

計算機プログラムの構造と解釈
ジェラルド・ジェイ サスマン ジュリー サスマン ハロルド エイブルソン
ピアソンエデュケーション
売り上げランキング: 6542
«
»