関数型言語の勉強にSICPを読もう - (9) 2章 - データによる抽象の構築(45-58ページ)

48ページ

以前にも一度 car、cdrを勉強したのですが、それが「なぜ必要か?」「その背景には何があるのか?」が分かりませんでした。
その答えの導入部は48ページに書いてあります。
ここを読んだだけではだめで、手続きの抽象化についてしっかり読んだ後に読むと良く分かります。

問題2.2

(define (make-segment p1 p2)
  (cons p1 p2))

(define (start-segment s)
  (car s))

(define (end-segment s)
  (cdr s))

(define (make-point x y)
  (cons x y))

(define (x-point p)
  (car p))

(define (y-point p)
  (cdr p))

(define (print-point p)
  (newline)
  (display "(")
  (display (x-point p))
  (display ",")
  (display (y-point p))
  (display ")"))


(define (midpoint-segment s)
  (define (mid-point a b)
    (/ (+ a b) 2))
  (make-point (mid-point (x-point (start-segment s)) (x-point (end-segment s)))
              (mid-point (y-point (start-segment s)) (y-point (end-segment s)))))

(print-point (midpoint-segment
              (make-segment (make-point 2 4) (make-point 4 8))))

プログラミング言語を学んでいる真っ最中はコピペをできるだけせず打ち込むことでいろいろ覚えていく気がする。

57ページ

そろそろSICPの勉強会を追い抜いたかなぁ。
一人で勉強しているとマイペースで出来るのが良いです。

問題2.17

(define (last-pair list)
  (if (null? (cdr list))
      (car list)
      (last-pair (cdr list))))

(last-pair (list 1 2 3 4))

問題2.18

苦戦した。
失敗の過程も書いておきます。

(define (reverse l)
  (cons (reverse (cdr l))
        (car l)))

何かエラーになるので、(backtrace)してみる。
するとcdrに空リストが渡っている雰囲気。

これでどうだろうか。

(define (reverse l)
  (if (null? (cdr l))
      l
      (cons (reverse(cdr l))
            (car l))))

null?でリストの終端かどうか調べる
結果

guile> ((((4) . 3) . 2) . 1)

うぅ・・。おしいな。
これは、listの結合がうまくいっていない。(car l)がlistじゃないのかな?

(define (reverse l)
  (if (null? (cdr l))
      l
      (cons (reverse(cdr l))
            (list (car l)))))

こうしてみる
だめだった。

guile> ((((4) 3) 2) 1)

うーん。はまってきた。
そうだ本にlistのappendが定義されていたからそれを使おう。

;; 泣きのappend
(define (append list1 list2)
  (if (null? list1)
      list2
      (cons (car list1) (append (cdr list1) list2))))

(define (reverse l)
  (if (null? (cdr l))
      l
      (append (reverse(cdr l))
            (list (car l)))))

(reverse (list 1 2 3 4))

できました。

これができた!と言えるためにはappendを理解してappendなしで書き直してみるのが良さそうだけど遠い。

appendは結局リストを作るので

(cons 1 (cons 2 (list 3 4))) = (list 1 2 3 4)

だよねということで納得。
つまりconsの第一引数にリストを突っ込んだらそれが値になるのでリストがつながらないという罠にはまっていたということか。




※「SICPを読もう」の目次はこちら


計算機プログラムの構造と解釈
Gerald Jay Sussman Julie Sussman Harold Abelson 和田 英一
ピアソンエデュケーション (2000/02)
売り上げランキング: 56,404