EoPL reading (29) 1.3.1 Free and Bound Variables
昨晩爆呑。芋焼酎のロックを水割りと勘違いしてガブ呑み。さすがに帰宅後に、は無理でした。そりゃいいとして試験の検討続行。
ええと、occurs-bound? の考え方てきには
- exp が '() なら #f を戻す
- exp が symbol なら #f を戻す
- (car exp) が 'lambda なら
- lambda body が occurs bound なら #t を戻す
- lambda body が occurs bound でないなら
- 引数の要素と var が同じ
- かつ (cddr exp) が occurs free なら #t を戻す
- 上記いずれでも無い場合、car 又は cdr 要素が occurs bound なら #t を戻す。どちらも #f なら #f を戻す
という事になるんですが、既に書いてる試験でカバーしてるのかどうか不明。現時点での試験が以下です。まず、occurs-free? な試験。
(use gauche.test) (add-load-path ".") (load "occurs-free-bound") (test-start "occurs-free") (test-section "ut") ;; E is a variable reference and E is the same as x (test* "(occurs-free? 'x 'x) should return #t" #t (occurs-free? 'x 'x)) (test* "(occurs-free? 'x 'y) should return #f" #f (occurs-free? 'x 'y)) ;; E is of the form (lambda (y) E), where y is different from x ;; and x occurs free in E' (test* "(occurs-free? 'x '(lambda (y) ())) should return #f" #f (occurs-free? 'x '(lambda (y) ()))) (test* "(occurs-free? 'x '(lambda (y) x)) should return #t" #t (occurs-free? 'x '(lambda (y) x))) (test* "(occurs-free? 'x '(lambda (y) y)) should return #f" #f (occurs-free? 'x '(lambda (y) y))) (test* "(occurs-free? 'x '(lambda (x) x)) should return #f" #f (occurs-free? 'x '(lambda (x) x))) (test* "(occurs-free? 'x '(lambda (a b c) ())) should return #f" #f (occurs-free? 'x '(lambda (a b c) ()))) (test* "(occurs-free? 'x '(lambda (a b c) x)) should return #t" #t (occurs-free? 'x '(lambda (a b c) x))) (test* "(occurs-free? 'x '(lambda (a b c) y)) should return #f" #f (occurs-free? 'x '(lambda (a b c) y))) (test* "(occurs-free? 'x '(lambda (v w x) x)) should return #f" #f (occurs-free? 'x '(lambda (v w x) x))) (test* "(occurs-free? 'x '(lambda (y) (a b c))) should return #f" #f (occurs-free? 'x '(lambda (y) (a b c)))) (test* "(occurs-free? 'x '(lambda (y) (v w x))) should return #t" #t (occurs-free? 'x '(lambda (y) (v w x)))) (test* "(occurs-free? 'x '(lambda (x) x)) should return #f" #f (occurs-free? 'x '(lambda (x) (v w x)))) (test* "(occurs-free? 'x '(lambda (a b c) (a b c))) should return #f" #f (occurs-free? 'x '(lambda (a b c) (a b c)))) (test* "(occurs-free? 'x '(lambda (a b c) (v w x))) should return #t" #t (occurs-free? 'x '(lambda (a b c) (v w x)))) (test* "(occurs-free? 'x '(lambda (v w x) (v w x))) should return #f" #f (occurs-free? 'x '(lambda (v w x) (v w x)))) (test* "(occurs-free? 'x '(lambda (y) (lambda (y) ()))) should return #f" #f (occurs-free? 'x '(lambda (y) (lambda (y) ())))) (test* "(occurs-free? 'x '(lambda (y) (lambda (y) x))) should return #t" #t (occurs-free? 'x '(lambda (y) (lambda (y) x)))) (test* "(occurs-free? 'x '(lambda (y) (lambda (y) y))) should return #f" #f (occurs-free? 'x '(lambda (y) (lambda (y) y)))) (test* "(occurs-free? 'x '(lambda (y) (lambda (x) x))) should return #f" #f (occurs-free? 'x '(lambda (y) (lambda (x) x)))) (test* "(occurs-free? 'x '(lambda (x) (lambda (y) y))) should return #f" #f (occurs-free? 'x '(lambda (x) (lambda (y) y)))) (test-end)
で、問題の occurs-bound? な試験が以下。
(use gauche.test) (add-load-path ".") (load "occurs-free-bound") (test-start "occurs-bound") (test-section "ut") (test* "(occurs-bound? 'x ()) should return #f" #f (occurs-bound? 'x ())) (test* "(occurs-bound? 'x 'x) should return #f" #f (occurs-bound? 'x 'x)) ;; E is of the form (lambda (y) E), where x occurs bound in E' ;; or x and y are the same variable and y occurs free in E' ;; (not (occurs-bound? 'x '(x))) (test* "(occurs-bound? 'x '(lambda (x) x)) should return #t" #t (occurs-bound? 'x '(lambda (x) x))) ;; (not (occurs-bound? 'x '(y))) (test* "(occurs-bound? 'x '(lambda (x) y)) should return #f" #f (occurs-bound? 'x '(lambda (x) y))) ;; (not (occurs-bound? 'x '(x))) (test* "(occurs-bound? 'x '(lambda (y) x)) should return #f" #f (occurs-bound? 'x '(lambda (y) x))) ;; (not (occurs-bound? 'x '(x))) (test* "(occurs-bound? 'x '(lambda (x y z) x)) should return #t" #t (occurs-bound? 'x '(lambda (x y z) x))) ;; (not (occurs-bound? 'x '(y))) (test* "(occurs-bound? 'x '(lambda (x y z) y)) should return #f" #f (occurs-bound? 'x '(lambda (x y z) y))) ;; (not (occurs-bound? 'x '(x))) (test* "(occurs-bound? 'x '(lambda (a b c) x)) should return #f" #f (occurs-bound? 'x '(lambda (a b c) x))) ;; (not (occurs-bound? 'x '(x y z))) (test* "(occurs-bound? 'x '(lambda (x) (x y z)) should return #t" #t (occurs-bound? 'x '(lambda (x) (x y z)))) ;; (not (occurs-bound? 'x '(y x z))) (test* "(occurs-bound? 'x '(lambda (x) (y x z)) should return #t" #t (occurs-bound? 'x '(lambda (x) (y x z)))) ;; (not (occurs-bound? 'x '(y z x))) (test* "(occurs-bound? 'x '(lambda (x) (y z x)) should return #t" #t (occurs-bound? 'x '(lambda (x) (y z x)))) ;; (not (occurs-bound? 'x '(a b c))) (test* "(occurs-bound? 'x '(lambda (x) (a b c))) should return #f" #f (occurs-bound? 'x '(lambda (x) (a b c)))) ;; (not (occurs-bound? 'x '(x y z))) (test* "(occurs-bound? 'x '(lambda (y) (x y z))) should return #f" #f (occurs-bound? 'x '(lambda (y) (x y z)))) ;; (occurs-bound? 'x '(lambda (x) x)) (test* "(occurs-bound? 'x '(lambda (y) (lambda (x) x))) should return #t" #t (occurs-bound? 'x '(lambda (y) (lambda (x) x)))) ;; (not (occurs-bound? 'x '(lambda (x) ()))) (test* "(occurs-bound? 'x '(lambda (y) (lambda (x) ()))) should return #f" #f (occurs-bound? 'x '(lambda (y) (lambda (x) ())))) ;; (not (occurs-bound? 'x '(lambda (x) y))) (test* "(occurs-bound? 'x '(lambda (y) (lambda (x) y))) should return #f" #f (occurs-bound? 'x '(lambda (y) (lambda (x) y)))) ;; 'x doesn't exist '(y) (test* "(occurs-bound? 'x '(lambda (y) (lambda (y) x))) should return #f" #f (occurs-bound? 'x '(lambda (y) (lambda (y) x)))) ;; (occurs-bound? 'x '(lambda (x y z) x)) (test* "(occurs-bound? 'x '(lambda (y) (lambda (x y z) x))) should return #t" #t (occurs-bound? 'x '(lambda (y) (lambda (x y z) x)))) ;; (not (occurs-bound? 'x '(lambda (x y z) y))) (test* "(occurs-bound? 'x '(lambda (y) (lambda (x y z) y))) should return #f" #f (occurs-bound? 'x '(lambda (y) (lambda (x y z) y)))) ;; (not (occurs-bound? 'x '(lambda (a b c) x))) (test* "(occurs-bound? 'x '(lambda (y) (lambda (a b c) x))) should return #f" #f (occurs-bound? 'x '(lambda (y) (lambda (a b c) x)))) ;; (occurs-bound? 'x '(lambda (x) (x y z))) (test* "(occurs-bound? 'x '(lambda (y) (lambda (x) (x y z)))) should return #t" #t (occurs-bound? 'x '(lambda (y) (lambda (x) (x y z))))) ;; (occurs-bound? 'x '(lambda (x) (y x z))) (test* "(occurs-bound? 'x '(lambda (y) (lambda (x) (y x z)))) should return #t" #t (occurs-bound? 'x '(lambda (y) (lambda (x) (y x z))))) ;; (occurs-bound? 'x '(lambda (x) (y z x))) (test* "(occurs-bound? 'x '(lambda (y) (lambda (x) (y z x)))) should return #t" #t (occurs-bound? 'x '(lambda (y) (lambda (x) (y z x))))) ;; (not (occurs-bound? 'x '(lambda (x) (a b c)))) (test* "(occurs-bound? 'x '(lambda (y) (lambda (x) (a b c)))) should return #f" #f (occurs-bound? 'x '(lambda (y) (lambda (x) (a b c))))) ;; (not (occurs-bound? 'x '(lambda (y) (x y z)))) (test* "(occurs-bound? 'x '(lambda (y) (lambda (y) (x y z)))) should return #f" #f (occurs-bound? 'x '(lambda (y) (lambda (y) (x y z))))) (test-end)
コメントが微妙ですがご容赦願います。今からカバレッジ具合を検証。
続き
ええと、(cddr exp) が occurs bound でないケイスの式を以下に列挙してみます。以下の式が occurs-free であれば #t が戻る。
- (lambda (x) ()) ;; not occurs free
- (lambda (x) y) ;; not occurs free
- (lambda (y) x)) ;; occurs free
- (lambda (x y z) y) ;; occurs free
- (lambda (a b c) x) ;; occurs free but
- (lambda (x) (a b c)) ;; not occurs free
- (lambda (y) (x y z)) ;; not occurs free
あら、結構少ないな。よく手続きを見てみるに、occurs bound ではなく、occurs free な式 (そうでないものも含む) の試験をきちんとヤッてるかどうか。
スデにカバー済みかどうかも微妙。あ、以下は少なくとも漏れてますね。
(lambda (x y z) a)
とか
(lambda (x) (x y z))
あ、下の方はそれ以前に occurs-bound? で #t になるのか。上側も微妙。まだ occurs-bound? の仕様をきちんと理解できてないな。(とほほ