EoPL reading (23) 1.3.1 Free and Bound Variables

エントリを改めます。以下な試験を追加したところ

(test-section "ut")
(test* "(occurs-free? 'y 'y) should return #t"
       #t
       (occurs-free? 'y 'y))
(test* "(occurs-free? 'x 'y) should return #f"
       #f
       (occurs-free? 'x 'y))
(test* "(occurs-free? 'x '(lambda (x) ())) should return #f"
       #f
       (occurs-free? 'x '(lambda (x) ())))
(test* "(occurs-free? 'x '(lambda (x) x)) should return #t"
       #t
       (occurs-free? 'x '(lambda (x) x)))
(test* "(occurs-free? 'x '(lambda (x) y)) should return #f"
       #f
       (occurs-free? 'x '(lambda (x) y)))

結果が微妙。

<ut>---------------------------------------------------------------------------
test (occurs-free? 'y 'y) should return #t, expects #t ==> ok
test (occurs-free? 'x 'y) should return #f, expects #f ==> ok
test (occurs-free? 'x '(lambda (x) ())) should return #f, expects #f ==> ok
test (occurs-free? 'x '(lambda (x) x)) should return #t, expects #t ==> ERROR: GOT #f
test (occurs-free? 'x '(lambda (x) y)) should return #f, expects #f ==> ok

あら、free だから #f で良いのか、てーコトは最後のが #t なのが微妙? あるいは 3 番目もか。そうか lambda 式の引数に var と同じシンボルがあったらダウトですね。
使われてなくても定義があれば occurs free ではないのか。で、以下を追加。

(test* "(occurs-free? 'x '(lambda (y) y)) should return #f"
       #f
       (occurs-free? 'x '(lambda (y) y)))
(test* "(occurs-free? 'x '(lambda (y) x)) should return #t"
       #t
       (occurs-free? 'x '(lambda (y) x)))

あと、失敗してた試験は #f が戻ること、という試験に書き換えてます。書いた試験を日本語に直してみると

  • (occurs-free? 'y 'y) は #t を戻すべき
  • (occurs-free? 'x 'y) は #t を戻すべき
  • (occurs-free? 'x '(lambda (x) ())) は #f を戻すべき
  • (occurs-free? 'x '(lambda (x) x)) は #f を戻すべき
  • (occurs-free? 'x '(lambda (x) y)) は #f を戻すべき
  • (occurs-free? 'x '(lambda (y) y)) は #t を戻すべき
  • (occurs-free? 'x '(lambda (y) x)) は #t を戻すべき

よく考えたら最初の_occurs free_の定義は面白い。ってかなんで最後の二つは上手く動くんでしょうか。
なるほど、上記のソレが関係してるのか。結局 lambda の body にて var が使われてないとダメなんだ。かつ引数に var が出現しなければ、という事ッスか。else な試験ってコトで以下を追加。

(test* "(occurs-free? 'x '(lambda (f) (lambda (x) (f x)))) should return #f"
       #f
       (occurs-free? 'x '(lambda (f) (lambda (x) (f x)))))
(test* "(occurs-free? 'f '(lambda (f) (lambda (x) (f x)))) should return #f"
       #f
       (occurs-free? 'f '(lambda (f) (lambda (x) (f x)))))
(test* "(occurs-free? 'y '(lambda (f) (lambda (x) (f x)))) should return #f"
       #f
       (occurs-free? 'y '(lambda (f) (lambda (x) (f x)))))
(test* "(occurs-free? 'y '(lambda (f) (lambda (x) (y x)))) should return #t"
       #t
       (occurs-free? 'y '(lambda (f) (lambda (x) (y x)))))

定義を見るに

  • lambda 式の引数はシンボル単発のみ許容
  • lambda 式の body はシンボル一発又は要素が二つのリストのみ許容

という形なのか。

occurs bound については

明日にします。reading gauche 方面に去ります。余力があれば kernel 方面も。