EoPL reading (96) 2.2 An Abstraction for Inductive Data Type
微妙な検討が続いています。未だもって腑にオチてなかったりして。
test (occurs-free? 'y '(lambda (x) (lambda (x) x))), expects #f ==> ok test (occurs-free? 'y '(lambda (x) (lambda (x) y))), expects #t ==> ok test (occurs-free? 'y '(lambda (x) (lambda (y) x))), expects #f ==> ok test (occurs-free? 'y '(lambda (x) (lambda (y) y))), expects #f ==> ok
上記で subst に渡されるのは
- (lambda (x) x)
- (lambda (y) x)
- (lambda (y) y)
の三つ。やっぱ置き換えなくて良いのかなぁ。でも
(lambda (x) (lambda (y) x))
を y で変換、は
(lambda (y0) (lambda (y) y0))
にならんとダメじゃないのかなぁ。うーん、手続き戻す手続きについて検討してるから微妙なのでしょうか。そういえば変換する問題があったな。最初に fresh-id しといて云々なのかも。
あと、lambda な分岐って
(lambda-exp (id body) (lambda-exp id body))
ではなくて
(lambda-exp (id body) (lambda-exp id (subst from to body)))
とか?
でも中のナニが occurs free だったらどうなるんだろ。なんか難しく考え杉なのかなぁ。で、上記な実装にして試験を書きかけたんですが、やはり
test (occurs-free? 'y '(lambda (x) (lambda (x) x))), expects #f ==> ok test (occurs-free? 'y '(lambda (x) (lambda (y) x))), expects #f ==> ok test (occurs-free? 'y '(lambda (x) (lambda (y) y))), expects #f ==> ok
にヒッカカってしまう。lambda の引数は一つ限定なので、同じならスルー、にすれば良いのか。こう?
(lambda-exp (id body) (lambda-exp id (if (eqv? from id) body (substitute from to body))))
試験を書いてみます。
(test* "(subst 'x 'y0 (lambda-exp x (var-exp x)))" '(lambda-exp x (var-exp x)) (substitute 'x 'y0 '(lambda-exp x (var-exp x)))) (test* "(subst 'x 'y0 (lambda-exp y (var-exp x)))" '(lambda-exp y (var-exp y0)) (substitute 'x 'y0 '(lambda-exp y (var-exp x)))) (test* "(subst 'x 'y0 (lambda-exp y (var-exp y)))" '(lambda-exp y (var-exp y)) (substitute 'x 'y0 '(lambda-exp y (var-exp y))))
パス。スデに fresh-id が考慮されてたりして。
あるいは以下。
test (occurs-free? 'y '(lambda (x) ((lambda (x) x) x))), expects #f ==> ok test (occurs-free? 'y '(lambda (x) ((lambda (x) x) y))), expects #t ==> ok test (occurs-free? 'y '(lambda (x) ((lambda (x) y) y))), expects #t ==> ok test (occurs-free? 'y '(lambda (x) ((lambda (x) y) x))), expects #t ==> ok test (occurs-free? 'y '(lambda (x) ((lambda (y) y) y))), expects #t ==> ok test (occurs-free? 'y '(lambda (x) ((lambda (y) y) x))), expects #f ==> ok test (occurs-free? 'y '(lambda (x) ((lambda (y) x) y))), expects #t ==> ok test (occurs-free? 'y '(lambda (x) ((lambda (y) x) x))), expects #f ==> ok
上記は #f 戻すのが
(lambda (x) ((lambda (x) x) x)) (lambda (x) ((lambda (y) y) x)) (lambda (x) ((lambda (y) x) x))
なんですが、いっちゃん下の op な lambda が微妙。先程手を入れた app な実装が以下になってまして
(app-exp (rator rand) (app-exp (cases expression rator (lambda-exp (id body) rator) (else (substitute from to rator))) (substitute from to rand))))))
op な lambda はスルー方式となっております。とすれば上記三つは以下に変換?
(lambda (y0) ((lambda (x) x) y0)) (lambda (y0) ((lambda (y) y) y0)) (lambda (y0) ((lambda (y) x) y0))
一番最後のナニは最適化したら
(lambda (x) x)
になるのになぁ。でもこれって subst に渡したらなんとかなりそげにも見える。こうしてみます。
(app-exp (rator rand) (app-exp (cases expression rator (lambda-exp (id body) (substitute from to rator)) (else (substitute from to rator))) (substitute from to rand))))))
で、以下の試験を書いた。
(test* "(subst 'x 'y0 ((lambda (x) x) x))" '(app-exp (lambda-exp x (var-exp x)) (var-exp y0)) (substitute 'x 'y0 '(app-exp (lambda-exp x (var-exp x)) (var-exp x)))) (test* "(subst 'x 'y0 ((lambda (y) y) x))" '(app-exp (lambda-exp y (var-exp y)) (var-exp y0)) (substitute 'x 'y0 '(app-exp (lambda-exp y (var-exp y)) (var-exp x)))) (test* "(subst 'x 'y0 ((lambda (y) x) x))" '(app-exp (lambda-exp y (var-exp y0)) (var-exp y0)) (substitute 'x 'y0 '(app-exp (lambda-exp y (var-exp x)) (var-exp x))))
を、試験にパスしたぞ。なんとなくええカンジ。
<substitute>------------------------------------------------------------------- test (subst 'x 'y (lit-exp 1)), expects (lit-exp 1) ==> ok test (subst 'x 'y (var-exp 'x)), expects (var-exp y) ==> ok test (subst 'y 'x (var-exp 'x)), expects (var-exp x) ==> ok test (subst 'x 'y0 (lambda-exp x (var-exp x))), expects (lambda-exp x (var-exp x)) ==> ok test (subst 'x 'y0 (lambda-exp y (var-exp x))), expects (lambda-exp y (var-exp y0)) ==> ok test (subst 'x 'y0 (lambda-exp y (var-exp y))), expects (lambda-exp y (var-exp y)) ==> ok test (subst 'x 'y0 ((lambda (x) x) x)), expects (app-exp (lambda-exp x (var-exp x)) (var-exp y0)) ==> ok test (subst 'x 'y0 ((lambda (y) y) x)), expects (app-exp (lambda-exp y (var-exp y)) (var-exp y0)) ==> ok test (subst 'x 'y0 ((lambda (y) x) x)), expects (app-exp (lambda-exp y (var-exp y0)) (var-exp y0)) ==> ok
とりあえず投入。