SICP 2.3

「長方形の違う表現を実装せよ」って言うから、左下の頂点と2辺の長さから長方形を定義するようにしてみた。これだと周の長さと面積の計算が楽。

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

(define make-rectangle cons)
(define p1-rectangle car)
(define p2-rectangle cdr)
(define (width-rectangle r)
  (let ((p1 (p1-rectangle r))
        (p2 (p2-rectangle r)))
    (abs (- (x-point p1) (x-point p2)))))
(define (height-rectangle r)
  (let ((p1 (p1-rectangle r))
        (p2 (p2-rectangle r)))
    (abs (- (y-point p1) (y-point p2)))))
(define (perimeter-rectangle r)
  (* (+ (width-rectangle r) (height-rectangle r)) 2))
(define (area-rectangle r)
  (* (width-rectangle r) (height-rectangle r)))

; test
(let ((p1 (make-point 2 5))
      (p2 (make-point 4 7)))
  (let ((r (make-rectangle p1 p2)))
    (print (perimeter-rectangle r))
    (print (area-rectangle r))))

; another way of abstraction
(define (make-rectangle2 p width height)
  (cons p (cons width height)))
(define point-rectangle2 car)
(define width-rectangle2 cadr)
(define height-rectangle2 cddr)
(define (perimeter-rectangle2 r)
  (let ((width (width-rectangle2 r))
        (height (height-rectangle2 r)))
    (* 2 (+ width height))))
(define (area-rectangle2 r)
  (let ((width (width-rectangle2 r))
        (height (height-rectangle2 r)))
    (* width height)))

; test
(let ((r (make-rectangle2 (make-point 1 3) 4 5)))
  (print (perimeter-rectangle2 r))
  (print (area-rectangle2 r)))