(sicp54)問題4.16

カッコひとつ足りないバグに2時間くらい費やした。

4.16

a

ただcheckをつけるだけ(わかりやすいように手続きでくくる)

(define (lookup-variable-value var env)
  (define (unassigned-varriable-checker pair)
    (if (eq? (cdr pair) '*unassigned*)
        (error "it is UNASSIGNED-VARIABLE" var)
        (cdr pair)))
  ((env-loop-maker  unassigned-varriable-checker
                    (cut error "Unbound variable" var))
   var env))
b
(define (scan-out-defines exps)
  (let iter ((rest exps) (l* '()) (s* '()) (b* '()))
    (define (found-define exp)
      (let ((var (definition-variable exp))
            (val (definition-value exp)))
        (iter (cdr rest)
              (cons (list var ''*unassigned*) l*)
              (cons (list 'set! var val) s*)
              b*)))
    (if (null? rest)
        (if (or (null? l*) (null? s*))
            exps
            `((let ,l* ,@s* ,@b*)))
        (if (eq? 'define (caar rest))
            (found-define (car rest))
            (iter (cdr rest) l* s* (cons (car rest) b*))))))
c

evalで処理するうちに変更して置くといい。(実行と解析の分離?)

  • procedure-body:applyで
  • make-procedure:evalで

そんなわけで、make-procedureの時にscan-out-definesを使った方がいいと思った。
変更点は以下のところだけ

(define (make-procedure parameters body env)
  ;(list 'procedure parameters body env))
  (list 'procedure parameters (scan-out-defines body) env)) ;ex 4.16 c
;;; M-Eval input:
(define (f x)
        (define (even? n)
          (if (= n 0) true (odd? (- n 1))))
        (define (odd? n)
          (if (= n 0) false (even? (- n 1))))
        (even? x))


;;; M-Eval value:
ok

;;; M-Eval input:
(f 10)

;;; M-Eval value:
#t