(wat-aro)

無職から有職者にランクアップしました

SICP 問題 4.27

遅延評価

;;; M-Eval input:
(define count 0)

;;; M-Eval value:
ok

;;; M-Eval input:
(define (id x)
  (set! count (+ count 1))
  x)

;;; M-Eval value:
ok

;;; M-Eval input:
(define w (id (id 10)))

;;; M-Eval value:
ok 

;;; M-Eval input:
count

;;; M-Eval value:
1

;;; M-Eval input:
w

;;; M-Eval value:
10

;;; M-Eval input:
count

;;; M-Eval value:
2

wを定義する時に(id (id 10))がevalされる.
aplication?からmy-applyに送られる.
この時にoperatorはactual-valueされるがoperandsはされない.
そこで(set! count (+ count 1))の行からcountが1になり,(id (id 10))の値は(thunk (id 10))として保存される..
その後,wを評価すると,(actual-value w)となるのでdelayしていた部分が全てforceされる.
しかし,この時点で(id (id 10))の値は(id 10)であると保存されているので(thunk (id 10))が返されるだけでset!行は実行されない.
そして(thunk (id 10))が評価されてcountが2になる.
 
環境の中身は以下のようになっている.

gosh> the-global-environment
#0=(((w id count driver-loop try false true car cdr cons null? = - + * /)
     (thunk (id 10) #0#)
     (procedure (x) ((set! count (+ count 1)) x) #0#)
     1
     (procedure ()
                ((prompt-for-input input-prompt)
                 (let ((input (read)))
                   (let ((output (actual-value input the-global-environment)))
                     (announce-output output)
                     (user-print output)))
                 (driver-loop)) #0#)
     (procedure (a b) ((if (= a 0) 1 b)) #0#)
     #f
     #t
     (primitive #<subr car>)
     (primitive #<subr cdr>)
     (primitive #<subr cons>)
     (primitive #<subr null?>)
     (primitive #<subr =>)
     (primitive #<subr ->)
     (primitive #<subr +>)
     (primitive #<subr *>)
     (primitive #<subr />)))

wの値は (thunk (id 10))になっている.