2016/01/07
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))
になっている.