EoPL reading (17) 1.2.4 Exercises

Exercise-1.18-2

ちょっと手を入れてみた。

(define (car&cdr s slist errvalue)
  (define (make-result s rslt)
    (if (null? rslt)
	s
	(list 'compose s rslt))
    )
  (define (car&cdr-inner rslt slist)
    (cond ((null? slist) errvalue)
	  ((eq? s (car slist)) (make-result 'car rslt))
	  ((pair? (car slist))
	   (let ((ret (car&cdr-inner (list 'compose 'car rslt) (car slist))))
	     (if (eq? errvalue ret)
		 (car&cdr-inner (make-result 'cdr rslt) (cdr slist))
		 ret)))
	  (else
	   (car&cdr-inner (make-result 'cdr rslt) (cdr slist))))
    )
  (car&cdr-inner '() slist)
  )

これ以上は無理。一応 REPL な環境で確認してみましたが、それなりにきちんと動いているように見えます。ってか実装見てもとりあえずなんとかなってそげ。

Exercise-1.18-3

compose 使うな、とある。確か compose の定義は

(define (compose p1 p2)
  (lambda (x) (p1 (p2 x))))

だったはずなんですが、そのままでいいのかなぁ。って試験書きかけてなんか微妙な事に気がついてます。例えば

(compose car (compose cdr cdr))

って

(lambda (x) (car (cdr (cdr x))))

ですよね。てーコトは最後に付けなきゃ、なんだ。これ、最後に、なナニでハマりました。あと、引数の x が、とかなんとか。あと fail 戻すナニが微妙。結果的に以下が出てきた。

(define (car&cdr s slist errvalue)
  (define (make-result s rslt)
    (if (null? rslt)
	(list s 'x)
	(list s rslt))
    )
  (define (car&cdr-inner rslt slist)
    (cond ((null? slist) errvalue)
	  ((eq? s (car slist))
	   (make-result 'car rslt))
	  ((pair? (car slist))
	   (let ((ret (car&cdr-inner (list 'car rslt) (car slist))))
	     (if (eq? errvalue ret)
		 (car&cdr-inner (make-result 'cdr rslt) (cdr slist))
		 ret)))
	  (else
	   (car&cdr-inner (make-result 'cdr rslt) (cdr slist))))
    )
  (let ((ret (car&cdr-inner '() slist)))
    (if (eq? ret errvalue)
	ret
	(list 'lambda '(x) ret)))
  )

苦労の後が偲ばれます。

make-result 手続きは以下?

  (define (make-result s rslt)
    (list s
          (if (null? rslt)
               'x
               rslt))
    )