(wat-aro)

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

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