SICP 読み (182) 4.2.2 遅延評価の解釈系
一応遅延評価なソレを盛り込んでみたんですが、まだきちんと理解できてないな。とりあえず問題 4.27 なナニを手動 eval する事で理解を深めたい。
そして保留な問題 4.26 は (以下略
問題 4.27
では順に見ていきます。実機確認は別途で。
(define count 0)
まず上記の式が eval される。この式は definition 認定されるので eval-definition に渡る。こんな感じか。env は the-global-environment と同一と見ます。
(eval-definition (define count 0) env)
これは以下のナニが適用。
(define-variable! count (eval 0 env) env)
で 'ok 戻して終わり。このあたりは変更ナシなのでスルーした方が良いかなぁ。
むしろ以降の方がポイント高いのかな??
(define (id x) (set! count (+ count 1)) x)
これも途中を略して以下かなぁ。
(define-variable! id (eval (lambda (x) (set! count (+ count 1)) x) env) env)
最終的に id が束縛されるのは以下の式になるはず。
(procedure (x) ((set! count (+ count 1)) x) env)
このあたりも修正入ってないんで既存の通りか。問題になってくるのは以降のナニですな。
(define w (id (id 10)))
w が束縛されるのは手続きになっている。途中を略して以下ですか。
(define-variable! w (eval (id (id 10)) env) env)
この右辺値が eval によってどう評価されるのか。というと渡されている式は application 認定なので以下のソレでしょうか。
(apply (actual-value id env) ((id 10)) env)
そろそろ微妙になりつつあります。(何
まず (actual-value id env) から。id が束縛されているリストは上記の通りですが、actual-value の定義が以下になっているので
(define (actual-value exp env) (force-it (eval exp env)))
えーと解釈系は作用的順序で評価されるはずなので id が eval される。と、id は variable 認定されて束縛されているナニを lookup して上記の
(procedure (x) ((set! count (+ count 1)) x) env)
が戻ってきて force-it に渡されるのか。memoize ではない force-it で見てみると上記の式は thunk ではありませんので、そのまま戻りますな。なので上記の式がそのまま apply に渡る、と。次は引数ですが、これは apply の中の話か。
apply の中では compound-procedure 認定ですので、最初に
(set! count (+ count 1))
が x を (id 10) に束縛した環境で評価される。正確には
(extend-environment '(x) (list-of-delayed-args ((id 10)) env) env)
で戻る環境。この式はどのように評価されるのか、というと (x) が (list-of-delayed-args ((id 10)) env) で束縛されたフレームが env に追加されたナニが戻る。右辺値は以下な模様。
((thunk (id 10) env))
早い話が x は (thunk (id 10) env) に束縛されている事になる方向でビンゴとして (遅延評価なんで当たり前か)、評価される式はどんな扱いを受けるんだろうか。フレームはこの時点ではあまり関係ないな。上記の set! で始まるリストは eval に渡ると assignment 認定。
(eval-assignment (set! count (+ count 1)) env)
これは以下にナニ。
(set-variable-value! count (eval (+ count 1) env) env)
count に設定される右辺値は基本手続きなんで delay はされんはず。これを信じると count には 10 が設定されますな。で、次は何だっけ。(を
長い
次は (eval x env) ですか。ちなみに x は (thunk (id 10) env) に束縛されています。順を追っていくと lookup されますがどうなるんだろ。ええと、(id 10) は (thunk (id 10) env) が戻るの??
あら? なんかワケワカだ。でもこのまま続けてみよう。(を
(id 10) が (thunk (id 10) env) を戻すとして、w に束縛されるのは
(id (thunk (id 10) env))
になるのか。ちなみに thunk な式の環境は the-global-environment なのかなぁ。
ループ気味
どっかでエアポケットにオチた気味。そのまま続けてみます。たぶん気のせい。(を
とりあえず以下か。
(apply (actual-value id env) ((thunk (id 10) env)) env)
で、(actual-value id env) は
(procedure (x) ((set! count (+ count 1)) x) env)
中略して上記を戻すはず。これは apply において compound-procedure 認定。引数 x がどうなるんでしょうか。x は (thunk (id 10) env) が束縛なんですが、右辺値は list-of-delayed-args で解決されるのかどうなのか。
てコトで、(thunk (id 10) env) は delay-it に渡されます。環境は the-global-environment のままと見ます。あら? (thunk (thunk (id 10) env) env) になるぞ。これが x に束縛されてるとしてどうなるんだろ。
このまま続ける
ええと、count は 2 になります。w は (thunk (thunk (id 10) env) env) です。これが (define w (id (id 10))) の戻りになるのかなぁ。
てー事は、この後に count の値を評価すると 2 が戻って、その後に w の値を評価したら (actual-value (thunk (thunk (id 10) env) env) env) が戻す 10 となるのか。
で、再度 count の値を評価すると、上記で (id 10) がもう一度評価されてるんで 3 が戻ってくる、という事になるのかなぁ。
実は実機で確認できんほどへろへろなんで再検討させて頂いて確認させて下さひ。(弱