EoPL reading (33) 1.3.1 Free and Bound Variables

Exercise.1-25

quote 盛り込め、との事。#f 戻せば良いだけのはずなので試験から検討。
とりあえず occurs-free? な試験から。
ええと、

test (occurs-free? 'x 'x) should return #t, expects #t ==> ok

という事なので以下を追加。

(test* "(occurs-free? 'x ’(quote x)) should return #f"
       #f
       (occurs-free? 'x ’(quote x)))

当たり前でしょうが、以下も #f か。

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

あるいは lambda 式の中なナニ。

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

しかしこれ、実装を考えたら手続きを作らずに云々かどうかが微妙。こんな試験を盛り込むかどうか悩みつつ

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

以下の実装を盛り込んで試験。

     ((pair? exp) (eq? (car exp) 'quote))

微妙。ってかダメだ。やっぱ手続き作らないと駄目ですね。cond はテストが #f なら次のテストに、なんですが pair? をテストにしてしまうと微妙。
なので、以下の手続きを追加。

(define (quote? exp)
  (if (pair? exp)
      (eq? (car exp) 'quote)
      #f))

で、試験してみたらパス。これは quote? な試験も盛り込み必要ですな。以下なカンジ。

(test* "(quote? 'x) should return #f"
       #f
       (quote? 'x))
(test* "(quote? 1) should return #f"
       #f
       (quote? 1))
(test* "(quote? '(x y)) should return #f"
       #f
       (quote? '(x y)))
(test* "(quote? '(quote x)) should return #t"
       #t
       (quote? '(quote x)))

一応 occurs-free? な試験ですが

  • (occurs-free? 'x '(quote x)) については E が variable reference ではないので #f
  • (occurs-free? 'x '(quote y)) も上記と同様
  • (occurs-free? 'x '(lambda (x) (quote x))) も E' は variable reference ではない
  • (occurs-free? 'x '(lambda (x) (if (= y (quote x)) #t #f))) についても E' において上記と同様の理由で occurs free と判断

という事で良いのだろうか。
あと occurs-bound? 方面も上記と同様の試験で良いのだろうか。

(test-section "ex.1-25")
(test* "(occurs-bound? 'x '(quote x)) should return #f"
       #f
       (occurs-bound? 'x '(quote x)))
(test* "(occurs-bound? 'x '(quote y)) should return #f"
       #f
       (occurs-bound? 'x '(quote y)))
(test* "(occurs-bound? 'x '(lambda (x) (quote x))) should return #f"
       #f
       (occurs-bound? 'x '(lambda (x) (quote x))))
(test* "(occurs-bound? 'x '(lambda (x) (if (= y (quote x)) #t #f))) should return #f"
       #f
       (occurs-bound? 'x '(lambda (x) (if (= y (quote x)) #t #f))))

パスした、と思ったら分岐が入ってない。一応下記を盛り込んで試験実施。

     ((quote? exp) #f)

試験はパスしてます。しかし盛り込みスルーで試験に通るってのはどうなんだろうか。という事で occurs-free? 及び occurs-bound? について上記の分岐をコメントアウトしてみたら試験にパスしませなんだ。なるほど。occurs-free? に盛り込み済みだからパスしたんだな。