SICP 読み (166) 4.1.6 内部定義

色々検討してますが問題 4.16 の c についてはまだ分からん状態。とりあえず、scan-out-defines がでっち上がった。ほぼ一発だった。びっくり。
以下の試験にパスしてます。

  ("4.16"
   ("scan-out-defines"
    (let ((l1 '((define (even? n) 
		  (if (= n 0) true (odd? (- n 1)))) 
		(define (odd? n) 
		  (if (= n 0) false (even? (- n 1))))
		(even? x)))
	  (l2 '(let ((even? '*unassigned*)
		     (odd? '*unassigned*))
		 (set! even? (lambda (n)
			       (if (= n 0) true (odd? (- n 1)))))
		 (set! odd? (lambda (n)
			      (if (= n 0) false (even? (- n 1)))))
		 (even? x))))
      (assert-equal l2 (scan-out-defines l1)))
    )
   )

実装が以下。

(define (scan-out-defines exp)
  (define (make-set exp)
    (let f ((init '()) (set '()) (exp exp))
      (cond ((null? exp)
	     (append (list 'let init) set))
	    (else
	     (cond ((definition? (car exp))
		    (f (append init (list (list (definition-variable (car exp))
						''*unassigned*)))
		       (append set (list (list 'set!
					       (definition-variable (car exp))
					       (definition-value (car exp)))))
		       (cdr exp)))
		   (else
		    (f init set (cdr exp))))))))
  (append (make-set exp)
	  (let f ((l '()) (exp exp))
	    (cond ((null? exp) l)
		  ((definition? (car exp))
		   (f l (cdr exp)))
		  (else
		   (f (append l (list (car exp))) (cdr exp)))))))

scan-out-defines はまだ修正の余地があるものと思われます (試験も十分ではないし) が、とりあえずメモ代わりに残しておかせて下さひ。(何処
しかし、この手続きに何らかのヒントがあったりするのかな、とも思ったんですが未だに c なソレが微妙なあたりが弱いな。