(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