EoPL reading (4) 1.2.4 Exercises

このあたりはなるべく機械的にイキたいのですが。

Exercise 1.15-5

試験は以下

(use gauche.test)

(add-load-path ".")
(load "exist?")

(test-start "1.15-5")
(test-section "test-exist?")
(test* "(exists? number? '(a b c 3 e))"
       #t
       (exists? number? '(a b c 3 e)))
(test* "(exists? number? '(a b c d e))"
       #f
       (exists? number? '(a b c d e)))
(test-end)

これは number? が真な時点で終了すれば良い。ので以下でしょうか。

(define (exists? pred lst)
  (if (null? lst)
      #f
      (if (pred (car lst))
	  #t
	  (exists? pred (cdr lst))))
  )

試験にはパスしてます。

Exercise 1.15-6

げ。vector が出てきた。pred が真になる最初のインデクスを戻せば良い、のかな。とりあえず試験を書いてみる。

(use gauche.test)

(add-load-path ".")
(load "vector-index")

(test-start "1.15-6")
(test-section "test-vector-index")
(test* "(vector-index (lambda (x) (eqv? x 'c)) '#(a b c d))"
       2
       (vector-index (lambda (x) (eqv? x 'c)) '#(a b c d)))
(test* "(vector-ref '#(a b c) (vector-index (lambda (x) (eqv? x 'b)) '#(a b c)))"
       'b
       (vector-ref '#(a b c) (vector-index (lambda (x) (eqv? x 'b)) '#(a b c))))
(test-end)

微妙ですが試験には失敗している模様。本体を書いてみる。最初に pred が真なインデクスを戻せば良いのか。一発書きだとどうすりゃ良いのやら。

(define (vector-index pred v)
  (define (inner-vector-index i)
    (if (> i (vector-length v))
	#f
	(if (pred (vector-ref v i))
	    i
	    (inner-vector-index (+ i 1)))))
  (inner-vector-index 0)
  )

試験が足らんな。見つからない場合、だけで良いのか。

(test* "(vector-index (lambda (x) (eqv? x 'e)) '#(a b c d))"
       #f
       (vector-index (lambda (x) (eqv? x 'e)) '#(a b c d)))

で、インデクスな比較演算が微妙なコトが判明。正しくは以下な模様

    (if (>= i (vector-length v))

Exercise 1.15-7

酔っぱらってきた。試験を以下に

(use gauche.test)

(add-load-path ".")
(load "list-set")

(test-start "1.15-7")
(test-section "test-list-set")
(test* "(list-set '(a b c d) 2 '(1 2))"
       '(a b (1 2) d)
       (list-set '(a b c d) 2 '(1 2)))
(test* "(list-ref (list-set '(a b c d) 3 '(1 5 10)) 3)"
       '(1 5 10)
       (list-ref (list-set '(a b c d) 3 '(1 5 10)) 3))
(test-end)

微妙な実装が以下

(define (list-set lst n x)
  (define (inner-list-set l i)
    (if (= i n)
	(cons x (cdr l))
	(cons (car l)
	      (inner-list-set (cdr l) (+ i 1))))
    )
  (inner-list-set lst 0)
  )

中の define でなんとかしてるあたり、微妙な気がしてるんですが。あと n が lst のインデクスを越えてたソレな対応が無いのはどうなのか。