SICPを読む(35) 問題2.2 - 2.3 オブジェクト指向っぽくなってきた。
オブジェクト指向っぽくなってきましたね。
今回は点と線、長方形の定義。グラフィックばっかりやってた時期があるので、馴染深い所です。
問題2.2
点と線を定義して、線の中点を出す問題。
;segment (define (make-segment start end) (cons start end)) (define (start-segment s) (car s)) (define (end-segment s) (cdr s)) (define (midpoint-segment s) (make-point (/ (+ (x-point (start-segment s)) (x-point (end-segment s))) 2) (/ (+ (y-point (start-segment s)) (y-point (end-segment s))) 2))) ; point (define (make-point x y) (cons x y)) (define (x-point p) (car p)) (define (y-point p) (cdr p)) (define (print-point p) (display (format "(~a, ~a)~%" (x-point p) (y-point p)))) (define segment1 (make-segment (make-point 1 2) (make-point 3 4))) (define segment2 (make-segment (make-point 5 6) (make-point 7 8))) (print-point (midpoint-segment segment1)) ; (2, 3) (print-point (midpoint-segment segment2)) ; (6, 7)
肩慣らし。
中点の計算も抽象化した方が良かったかも。
修正
(define (midpoint-segment s) (define (mid f) (/ (+ (f (start-segment s)) (f (end-segment s))) 2)) (make-point (mid x-point) (mid y-point)))
スッキリ!!
問題2.3
長方形の周囲の長さと、面積を出す問題。
まずは、((x1, y1),(x2, y2))の形。
; rect (define (make-rect start end) (cons start end)) (define (start-rect r) (car r)) (define (end-rect r) (cdr r)) ; width & height (define (rect-width r) (abs (- (x-point (start-rect r)) (x-point (end-rect r))))) (define (rect-height r) (abs (- (y-point (start-rect r)) (y-point (end-rect r))))) (define (rect-perimeter r) (* 2 (+ (rect-width r) (rect-height r)))) (define (rect-area r) (* (rect-width r) (rect-height r))) (define rect (make-rect (make-point 1 2) (make-point 3 4))) (rect-perimeter rect) ; 8 (rect-area rect) ; 4
最初、absしなかったので、マイナスになった(汗
共通する処理、rect-width,rect-heightを定義しました。もう1段階抽象化出来そう。
修正
; width & height (define (size-calc f r) (abs (- (f (start-rect r)) (f (end-rect r))))) (define (rect-width r) (size-calc x-point r)) (define (rect-height r) (size-calc y-point r))
次。
((x, y), (width, height))の形。
; rect (define (make-rect start size) (cons start size)) (define (start-rect r) (car r)) (define (size-rect r) (cdr r)) ; width & height (define (rect-width r) (x-point (size-rect r))) (define (rect-height r) (y-point (size-rect r))) (define rect (make-rect (make-point 1 2) (make-point 3 4))) (rect-perimeter rect) ; 10 (rect-area rect) ; 6
こっちの方が好きかな。rect-width,rect-heightを定義しておいたので、計算をサボることが出来た!!
良好な抽象ってこんな感じ?
バグ
- 割り切れないと分数になってしまった。(make-point 1.0 2.0)としたほうがいい。
- 修正がめんどいのでそのまま(汗
まとめ
- 長いけど、あっさり終わっちゃった。
- 線は点とオフセット、点と角度と長さでも表すことが出来る。アルゴリズムによって変えよう。
- クラスが無くてもクラスっぽい事は可能。
- リストだけでも、今までとあんまり変わらない感じで定義出来ることがわかった。
- これがどのように変化していくのか楽しみ。