(ns sicp.ex2_3 (:use [sicp ex2_2 utils] [clojure.test])) (declare width-rect height-rect) ;; wishful thinking. Assume that constructors and selectors are ;; available. Now compute perimeter. (defn perimeter-rect [rect] (* 2 (+ (width-rect rect) (height-rect rect)))) (defn area-rect [rect] (* (width-rect rect) (height-rect rect))) ;; now implement the rectangle. One way to represent a rectangle ;; is to use a pair of points representing diagonal corners. (defn make-rect [p1 p2] (list p1 p2)) (defn p1-rect [r] (first r)) (defn p2-rect [r] (first (rest r))) (defn width-rect [r] (let [p1 (p1-rect r) p2 (p2-rect r)] (abs (- (x-point p1) (x-point p2))))) (defn height-rect [r] (let [p1 (p1-rect r) p2 (p2-rect r)] (abs (- (y-point p1) (y-point p2))))) (deftest test-rect-perimeter-square (is (= (perimeter-rect (make-rect (make-point 0 0) (make-point 1 1))) 4))) (deftest test-rect-area-square (is (= (area-rect (make-rect (make-point 0 0) (make-point 2 2))) 4))) ;; part2 - another implementation ;; instead of coordinates, we store height and width itself. (defn make-rect-1 [h w] (list h w)) (defn width-rect-1 [r] (first r)) (defn height-rect-1 [r] (first (rest r))) ;; the below routines are unmodified versions of the above ;; procedures, but renamed to work around the compiler. Is ;; there a simpler way? (defn perimeter-rect-1 [rect] (* 2 (+ (width-rect-1 rect) (height-rect-1 rect)))) (defn area-rect-1 [rect] (* (width-rect-1 rect) (height-rect-1 rect))) (deftest test-rect-perimeter-square-1 (is (= (perimeter-rect-1 (make-rect-1 1 1)) 4))) (deftest test-rect-area-square-1 (is (= (area-rect-1 (make-rect-1 2 2)) 4)))