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 強力だな。