EoPL reading (77) 2.2 An Abstraction for Inductive Data Type

マルっと纏める方向で現実トウヒ。var-exp な分岐の以下の部分を

	   (var-exp (id)
		    (if (memq id arg)
			(if (or (null? rslt)
				(not (memq id rslt)))
			    (append rslt (list id))
			    rslt)
			rslt))

手続きにしてしまって渡せば良いな、とゆーコトで以下。

(define (bound-vars-test func l)
;; 中略
	   (var-exp (id)
		    (func id arg rslt))

で、呼び出し側で以下。

(define (bound-vars l)
  (bound-vars-test (lambda (id arg rslt)
		     (if (memq id arg)
			 (if (or (null? rslt)
				 (not (memq id rslt)))
			     (append rslt (list id))
			     rslt)
			 rslt))
		   (parse-expression l)))

試験パス。free-vars の定義も以下に。

(define (free-vars l)
  (bound-vars-test (lambda (id arg rslt)
		     (if (memq id arg)
			 rslt
			 (if (or (null? rslt)
				 (not (memq id rslt)))
			     (append rslt (list id))
			     rslt)))
		   (parse-expression l)))

これはこれは、と言いつつ最初は以下になってて

(define (bound-vars-test f l)
  (let f ((rslt '()) (arg '()) (l l))
    (cases expression l
	   (nul-exp (datum) rslt)
	   (lit-exp (num) rslt)
	   (var-exp (id)
		    (f id arg rslt))

何故に試験にパスしない、と悩んでたりもしてました(とほほほ
# 中の f と引数の f がバッティング
# いつも f って名前つけちゃう安易さが仇に。。
最後に bound-vars-test (名前微妙)手続き定義を以下に。

(define (bound-vars-test func l)
  (let f ((rslt '()) (arg '()) (l l))
    (cases expression l
	   (nul-exp (datum) rslt)
	   (lit-exp (num) rslt)
	   (var-exp (id)
		    (func id arg rslt))
	   (if-exp (test-exp true-exp false-exp)
		   (let ((rslt1 (f rslt arg test-exp)))
		     (let ((rslt2 (f rslt1 arg true-exp)))
		       (f rslt2 arg false-exp))))
	   (lambda-exp (ids body)
		       (f rslt (append arg ids) body))
	   (app-exp (rands)
		    (let app-exp-inner ((rslt rslt) (rands rands))
		      (if (null? rands)
			  rslt
			  (app-exp-inner (f rslt arg (car rands))
					 (cdr rands)))))
	   )))

追記

これ、abstract syntax 使ったからこーゆー書き方ができたの?って思ったんですが、今になって見返してみたら Exercise 1.19 でも取り纏めは可能だった模様。
ただ、こうしたお陰で可読性が上がったのは鉄板かと。define-syntax 強力だな。