EoPL reading (26) 1.3.1 Free and Bound Variables

昨晩のナニを一日ネカせて再度試験を一から確認してみます。
と言いつつ、ut って不足あるな、と思ってたりして ...
# これって occurs free も同様
再度 occurs bound の定義を以下に。

  • 式 E は (lambda (y) E') な式
    • E' において x が occurs bound である
    • 又は x と y が同じ変数であり、y が E' において occurs free である

という記述になっている。又リストである場合にはいずれかの要素が occurs bound である事、という条件か。てーコトは

test (occurs-bound? 'x '((lambda (x y) (+ x y)) x z)) should return #f, expects #f ==> ERROR: GOT #t
test (occurs-bound? 'y '((lambda (x y) (+ x y)) x y)) should return #f, expects #f ==> ERROR: GOT #t
test (occurs-bound? 'x '((lambda (x y) (+ x y)) x y)) should return #f, expects #f ==> ERROR: GOT #t

上記は occurs bound 認定でないと駄目ですな。ちなみに上記は occurs free も真のはず。あるいは以下も

test (occurs-bound? 'x '((lambda (x y z) (((lambda (x) x) +) x y z) a b x)) should return #f: expects #f => got #t

occurs bound ですな。何の試験をしたかったのか今となっては謎。あ、成程。occurs free の試験を丸ごとコピーしてその逆書いたんだ。試験として微妙と言わざるを得ませんな。最終的に以下なカンジに。

<ex.1-22>----------------------------------------------------------------------
test (occurs-bound? 'z '((lambda (a b) (+ a b)) x y)) should return #f, expects #f ==> ok
test (occurs-bound? 'y '((lambda (a b) (+ a b)) x y)) should return #f, expects #f ==> ok
test (occurs-bound? 'x '((lambda (a b) (+ a b)) x y)) should return #f, expects #f ==> ok
test (occurs-bound? 'x '((lambda (x y z) (((lambda (x) x) +) x y z) a b x)) should return #t, expects #t ==> ok
test (occurs-bound? '+ '((lambda (x y z) (((lambda (x) x) +) x y z) a b x)) should return #f, expects #f ==> ok
test (occurs-bound? 'a '((lambda (x y z) (((lambda (x) x) +) x y z) a b x)) should return #f, expects #f ==> ok
test (occurs-bound? 'b '((lambda (x y z) (((lambda (x) x) +) x y z) a b x)) should return #f, expects #f ==> ok
test (occurs-bound? 'y '((lambda (x y z) (((lambda (x) x) +) x y z) a b x)) should return #t, expects #t ==> ok
test (occurs-bound? 'z '((lambda (x y z) (((lambda (x) x) +) x y z) a b x)) should return #t, expects #t ==> ok

なんか微妙。試験の品質悪いな。もう少し頭をヒヤす方向で次の問題に行きます。(を

Exercise-1.23

これって cond な条件分岐に (eqv? (car exp) 'if) な分岐が加われば良いのでしょうけれど、どうなれば良いのかな。
こんなカンジ?

((eqv? (car exp) 'if)
 (or (occurs-free? var (cadr exp))
     (occurs-free? var (cddr exp))))

でもこのケイスって、いきなり if が出てきたら、、、って思ったら occurs free なのか。リストが扱えるようになったからこうした syntax のナニが可能になったのか。
で、ちょっとへろへろなので微妙ですが、以下の試験をでっち上げてみました。

(test-section "ex.1-23")
;; E is of the form (lambda (y) E'), where y is not different from x
(test* "(occurs-free? 'x '(lambda (x) (if (= x 1) #f #t))) should return #f"
       #f
       (occurs-free? 'x '(lambda (x) (if (= x 1) #f #t)))
       )

;; E is of the form (lambda (y) E'), where y is different from x 
;; but x doesn't occurs free in E'
(test* "(occurs-free? 'x '(lambda (y) (if (= x 1) #f #t))) should return #t"
       #t
       (occurs-free? 'x '(lambda (y) (if (= x 1) #f #t)))
       )

;; E is of the form (lambda (y) E'), where y is not different from x
(test* "(occurs-free? 'x '(lambda (x) (if (= y 1) #f #t))) should return #f"
       #f
       (occurs-free? 'x '(lambda (x) (if (= y 1) #f #t)))
       )

;; E is of the form (lambda (y) E'), where y is different from x 
;; but x doesn't occurs free in E'
(test* "(occurs-free? 'x '(lambda (y) (if (= y 1) #f x))) should retuen #t"
       #t
       (occurs-free? 'x '(lambda (y) (if (= y 1) #f x)))
       )

;; E is of the form (lambda (y) E'), where y is different from x 
;; but x doesn't occurs free in E'
(test* "(occurs-free? 'x '(lambda (y) (if (= y 1) x #f))) should retuen #t"
       #t
       (occurs-free? 'x '(lambda (y) (if (= y 1) x #f)))
       )

で、以下を追加して

     ((eqv? (car exp) 'if)
      (or (occurs-free? var (cadr exp))
	  (occurs-free? var (cddr exp))))

試験動かしたら以下。

 make
Testing occurs-bound ...                                         passed.
Testing occurs-free ...                                          failed.
discrepancies found.  Errors are:
test (occurs-free? 'x '(lambda (y) (if (= y 1) #f x))) should retuen #t: expects #t => got #<error "pair required, but got 1">
test (occurs-free? 'x '(lambda (y) (if (= y 1) x #f))) should retuen #t: expects #t => got #<error "pair required, but got 1">
$

これ、SICP の self-evaluating? な述語が必要そげ。以下な実装で試験パス。

(define occurs-free?
  (lambda (var exp)
    (define (self-evaluating? s)
      (or (number? exp)
	  (string? exp)
	  (eq? #t exp)
	  (eq? #f exp)))

    (cond
     ((null? exp) #f)
     ((self-evaluating? exp) #f)
     ((symbol? exp) (eqv? exp var))
     ((eqv? (car exp) 'lambda)
      (and (not (let f ((l (cadr exp)))
		  (cond ((null? l) #f)
			((eqv? (car l) var) #t)
			(else
			 (f (cdr l))))))
	   (occurs-free? var (cddr exp))))
     ((eqv? (car exp) 'if)
      (or (occurs-free? var (cadr exp))
	  (occurs-free? var (cddr exp))))
     (else
      (or (occurs-free? var (car exp))
	  (occurs-free? var (cdr exp)))))))

なんか試験が微妙です。今日は体調微妙なんで早めに寝ます。

なんだこれわ

(define occurs-free?
  (lambda (var exp)
    (define (self-evaluating? s)
      (or (number? exp)
	  (string? exp)
	  (eq? #t exp)
	  (eq? #f exp)))

試験パスしてる事にびっくり。(を
だめだ。やっぱ疲れているみたい。今度こそもう寝ます。