SICP 全笔记

Exercise 2.3. Implement a representation for rectangles in a plane. (Hint: You may want to make use of exercise 2.2.) In terms of your constructors and selectors, create procedures that compute the perimeter and the area of a given rectangle. Now implement a different representation for rectangles. Can you design your system with suitable abstraction barriers, so that the same perimeter and area procedures will work using either representation?

要实现一个平面矩形的表示,我们只需要点就可以,并且,我们就只需要矩形的对角的 2 个点就可以确定矩形的位置和大小。

首先定义矩形上的操作:

;; first, define the operation
(define (perimeter retangle)
  (+ (* 2 (length retangle))
     (* 2 (width retangle))))

(define (area retangle)
  (* (length retangle)
     (width retangle)))

根据这些操作,我们需要定义矩形的 selector 和 constructor:

;;; retangle
;;  A  +-------------------+ D
;;     |                   |
;;     |                   |
;;  B  +-------------------+ C
(define (make-retangle A C)
  (let ((B (make-point (x-point A) (y-point C)))
        (D (make-point (x-point C) (y-point A))))
    (list A B C D)))

(define (length retangle)
  (let ((A (car retangle))
        (D (cadddr retangle)))
    (points-len A D)))

(define (width retangle)
  (let ((A (car retangle))
        (B (cadr retangle)))
    (points-len A B)))

最后是最基础的点的表示:

;;; get length between two points
(define (points-len p1 p2)
  (let ((len1 (abs (- (x-point p1) (x-point p2))))
        (len2 (abs (- (y-point p1) (y-point p2)))))
    (sqrt (+ (* len1 len1)
             (* len2 len2)))))

;;; point data structure
(define (make-point x y)
  (cons x y))

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

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

在测试中,我们选择点 (1, 3) (8, 1) 作为矩形的对角的两个点,对这个矩形进行周长和面积的测试。

(load "../testframe.scm")

(let* ((A (make-point 1 3))
       (C (make-point 8 1))
       (ret (make-retangle A C)))
  (begin
    (assert= 18 (perimeter ret))
    (assert= 14 (area ret))))