2016/02/09
SICP 問題 5.39
文面アドレスと実行時環境とり値を検索するlexical-address-lookupと 値を変更するlexical-address-set!を実装する.
;;; 文面アドレスを使って変数の値を探す
(define (lexical-address-lookup lex-add r-env)
(let ((frame (frame-values (list-ref r-env (car lex-add)))))
(let ((val (list-ref frame (cadr lex-add))))
(if (eq? val '*unassigned*)
(error "*Unassigned* variable")
val))))
;;; 文面アドレスにある値を変更する
(define (lexical-address-set! lex-add val r-env)
(let ((frame (frame-values (list-ref r-env (car lex-add)))))
(define (iter frame count)
(if (= count 0)
(begin (set-car! frame val)
'ok)
(iter (cdr frame) (- count 1))))
(iter frame (cadr lex-add))))
test
gosh> (define my-env (extend-environment '(x y) '(1 2) the-global-environment))
my-env
gosh> my-env
(((x y) 1 2)
((false true car cdr cons null? = - + * / > <)
#f
#t
(primitive #<subr car>)
(primitive #<subr cdr>)
(primitive #<subr cons>)
(primitive #<subr null?>)
(primitive #<subr =>)
(primitive #<subr ->)
(primitive #<subr +>)
(primitive #<subr *>)
(primitive #<subr />)
(primitive #<subr >>)
(primitive #<subr <>)))
gosh> (lexical-address-lookup '(0 0) my-env)
1
gosh> (lexical-address-lookup '(0 1) my-env)
2
gosh> (lexical-address-lookup '(1 0) my-env)
#f
gosh> (lexical-address-lookup '(1 1) my-env)
#t
gosh> (lexical-address-set! '(0 0) 'scheme my-env)
ok
gosh> (lexical-address-lookup '(0 0) my-env)
scheme
gosh> (lexical-address-set! '(1 1) 'SICP my-env)
ok
gosh> (lexical-address-lookup '(1 1) my-env)
SICP