SICP独習会〜抽象の壁(問題2.2〜2.3)〜
問題2.2
(define (make-segment x y) (cons x y)) (define (start-segment x) (car x)) (define (end-segment x) (cdr x)) (define (make-point a b) (cons a b)) (define (x-point x) (car x)) (define (y-point y) (cdr y)) (define (midpoint-segment a) (cons (/ (+ (x-point (start-segment a)) (x-point (end-segment a))) 2) (/ (+ (y-point (start-segment a)) (y-point (end-segment a))) 2)))
問題2.3
以下が最初に書いたソース。
(define rectangle-a (cons (make-segment (make-point 1 4) (make-point 1 -4)) (make-segment (make-point -1 4) (make-point -1 -4)))) (define rectangle-b (cons (make-segment (make-point 3 1) (make-point 3 -1)) (make-segment (make-point -3 1) (make-point -3 -1)))) ; 線分の長さを求める手続き ; 2点からの線分の長さを求める方法を忘れた (define (seg-lenght x) ) (define (rect-perimeter rect) (* 2 (+ (seg-lenght (car rect)) (seg-lenth (cdr (rect))))) (define (rect-area rect) (* (seg-lenght (car rect)) (seg-lenght (cdr rect)))
ここでは、とりあえず2種類の長方形を定義して書いてみた。その後、「2点からの線分の長さを求めるアルゴリズム」がわからなかったので、解答集みることに。解答集の答えと比較して気づいたことは、
ということである。(本にはバッチリ書いてありますが。「頭でなく体で理解した!!」という感じということで。)
私の書いた長方形の周囲の長さを求める手続き「rect-perimeter」と、長方形の面積を求める手続き「rect-area」の
ように、直に(選択子を介さずに)データを取得すると、解答集のように、長方形のデータに変更があったときに、これらの手続きも変更しなくてはいけないことになる。これは、うまく抽象化をできていない例だと言える。
(car rect)
2点から線分の長さを求めるアルゴリズムは、ここでは重要ではないので暇があったら復習しておくことにする。
で、以上のことを踏まえて書き直したソースが以下の通り。
(define (def-rect a b) (cons a b)) ;selector (define (bottom rect) (car a)) ;selector (define (height rect) (cdr b)) (define (seg-lenght) ) (define (rect-perimeter rect) (* 2 (+ (seg-length bottom) (seg-lenght height))) (define (rect-area rect) (* (seg-lenght bottom) (seg-lenght height)))
仮に、解答集のように長方形を構成データを変更したとしても、セレクターを変更すれば良いだけですむようになる。