EoPL reading (41) 1.3.1 Free and Bound Variables
Exercise.1-32
(test* "(un-lexical-address '(lambda (a) (: 0 1)))
should return #f"
#f
(un-lexical-address '(lambda (a) (: 0 1))))な試験を書いて make してみたらパスしない。とりあえず call/cc 使うべ、と言いつつ手続きに盛り込んだのですがそれでも NG。
ぢつは元々の処理の以下の部分
(else (if (eqv? (car l) ':) (let f ((d 0) (dict dict)) (cond ((null? dict) #f) ((eq? (cadr l) d) (let f-inner ((p 0) (dict (car dict))) (if (eq? (caddr l) p) (car dict) (f-inner (+ p 1) (cdr dict))))) (else (f (+ d 1) (cdr dict)))))
の f-inner な内部手続き (というかループ) の条件分岐に null? な判断が無かったのが原因でした。やはりヌケがあったか。
以下の試験
(use gauche.test)
(add-load-path ".")
(load "un-lexical-address")
(test-start "un-lexical-address")
(test-section "un-lexical-address")
(test* "(un-lexical-address '(lambda (a) (: 0 0)))
should return (lambda (a) a)"
'(lambda (a) a)
(un-lexical-address '(lambda (a) (: 0 0))))
(test* "(un-lexical-address '(lambda (a) (: 0 1)))
should return #f"
#f
(un-lexical-address '(lambda (a) (: 0 1))))
(test* "(un-lexical-address '(lambda (a) (: 1 0)))
should return #f"
#f
(un-lexical-address '(lambda (a) (: 1 0))))
(test* "(un-lexical-address '(lambda (a)
(lambda (b c)
((: 1 0) (: 0 0) (: 0 1)))))
should return (lambda (a) (lambda (b c) (a b c)))"
'(lambda (a) (lambda (b c) (a b c)))
(un-lexical-address '(lambda (a)
(lambda (b c)
((: 1 0) (: 0 0) (: 0 1))))))
(test-end)に一応パスしている実装が以下です。
(define (un-lexical-address exp)
(call/cc
(lambda (cont)
(letrec ((un-lexical-address-inner
(lambda (rslt dict l)
(cond ((null? l) rslt)
((eqv? (car l) 'lambda)
(un-lexical-address-inner (append rslt `(lambda ,(cadr l)))
(cons (cadr l) dict) (cddr l)))
(else
(if (eqv? (car l) ':)
(let f ((d 0) (dict dict))
(cond ((null? dict) (cont #f))
((eq? (cadr l) d)
(let f-inner ((p 0) (dict (car dict)))
(cond ((null? dict) (cont #f))
((eq? (caddr l) p) (car dict))
(else
(f-inner (+ p 1) (cdr dict))))))
(else
(f (+ d 1) (cdr dict)))))
(let g ((rslt rslt) (l l))
(if (null? l)
rslt
(g (append rslt (list (un-lexical-address-inner '()
dict
(car l))))
(cdr l))))
)
)))))
(un-lexical-address-inner '() '() exp)))))微妙に横に長いんですが、ご容赦をば。