SICP 読み (157) 4.1.2 式の表現
昨晩の続き。
(set! x ((lambda (x) (+ x 1)) x))
の評価について。x は大域環境で 1 に束縛されているのが前提で。
まず、このリストは eval にて assignment? が true と判断。なので eval-assignment に環境とリストが渡される。
(eval-assignment '(set! x ((lambda (x) (+ x 1)) x)) env)
そん中でどうなるか、というと以下。
(set-variable-value! (assignment-variable exp) (eval (assignment-value exp) env) env)
引数を当てはめてみるとこうなる。
(set-variable-value! (assignment-variable '(set! x ((lambda (x) (+ x 1)) x))) (eval (assignment-value '(set! x ((lambda (x) (+ x 1)) x))) env) env)
assignment-* がナニされて以下。
(set-variable-value! 'x (eval '((lambda (x) (+ x 1)) x) env) env)
順番として先に eval で始まるリストがナニ。これは eval で application と評価されて apply に渡される。こんなカンジでしょうか。
(apply (eval '(lambda (x) (+ x 1)) newenv) (list-of-values '(x) newenv))
これはこの環境では 2 と評価されるので、set-variable-value! が x の束縛は見つけて 2 を設定する、という若干ハショッたナニで解決。
束縛 (definition)
set と define の違いを見ると面白い。
(define (set-variable-value! var val env) (define (env-loop env) (define (scan vars vals) (cond ((null? vars) (env-loop (enclosing-environment env))) ((eq? var (car vars)) (set-car! vals val)) (else (scan (cdr vars) (cdr vals))))) (if (eq? env the-empty-environment) (error "Unbound variable -- SET!" var) (let ((frame (first-frame env))) (scan (frame-variables frame) (frame-values frame))))) (env-loop env)) (define (define-variable! var val env) (let ((frame (first-frame env))) (define (scan vars vals) (cond ((null? vars) (add-binding-to-frame! var val frame)) ((eq? var (car vars)) (set-car! vals val)) (else (scan (cdr vars) (cdr vals))))) (scan (frame-variables frame) (frame-values frame))))
何が違う、と言うと
- set は束縛を大域環境まで探索。大域環境に定義が無ければエラー。
- define はカレントな環境しか見ない。カレントな環境に束縛が無ければ定義してしまう。
なんか調子悪い、が言いわけにならん位の質の低さだな。練習問題 4.11 とかにとりかかった方が前向きな気もしています。とりあえずヤリたい放題なスペースなんで方向転換ありかも。(を