Решение упражнения 2.3 из SICP

17 January, 2008 (21:29) | Решения упражнений

Я рассмотрю это упражнение в несколько упрощенной форме. Будем считать, что прямоугольники ориентированы вдоль осей координат. Более общий случай рассмотрен, например, на SICP Wiki, но и упрощенного варианта вполне достаточно для демонстрации основных идей.

При любом представлении прямоугольника его периметр равен удвоенной сумме длин смежных сторон, а площадь равна произведению длин смежных сторон:

(define (rectangle-perimeter rectangle)
  (* 2 (+ (rectangle-width rectangle)
          (rectangle-height rectangle))))
(define (rectangle-area rectangle)
  (* (rectangle-width rectangle)
     (rectangle-height rectangle)))

Первый способ представления прямоугольников - это представление двумя противоположными угловыми точками (я их назвал левой верхней и правой нижней, но это не принципиально). Это представление задается так:

(define (make-rectangle topleft bottomright)
  (cons topleft bottomright))
(define (rectangle-topleft rectangle)
  (car rectangle))
(define (rectangle-bottomright rectangle)
  (cdr rectangle))
(define (rectangle-width rectangle)
  (abs (- (x-point (rectangle-topleft rectangle))
          (x-point (rectangle-bottomright rectangle)))))
(define (rectangle-height rectangle)
  (abs (- (y-point (rectangle-topleft rectangle))
          (y-point (rectangle-bottomright rectangle)))))

Второй способ представления прямоугольников - заданием левого верхнего угла (точки), а также ширины и длины). Это представление задается так:

(define (make-rectangle topleft width height)
  (cons topleft (cons width height)))
(define (rectangle-topleft rectangle)
  (car rectangle))
(define (rectangle-width rectangle)
  (car (cdr rectangle)))
(define (rectangle-height rectangle)
  (cdr (cdr rectangle)))

Как видим, процедуры вычисления периметра и площади остаются неизменными при переходе от одного представления к другому. Они не изменятся и в случае, когда мы будем использовать более сложные представления для прямоугольников, ориентированных на плоскости произвольным образом.

Comments

Comment from gorilych
Date: July 17, 2008, 2:02 pm

Как я понял, смена представления не должна затрагивать интерфейсов основных функций, а здесь меняется набор и значения параметров для процедуры make-rectangle

Тем не менее, основное требование (”одни и те же процедуры вычисления периметра и площади работали с любым из Ваших представлений”) выполнено ибо rectangle-perimeter и rectangle-area не используют конструктор.

Comment from eugene0
Date: January 21, 2009, 9:53 am

На мой взгляд, это не очень хорошее решение, т.к. ваши определения не могут сосуществовать в одной системе, а значит практической пользы от такого полиморфизма нет. Я бы сделал так:


(define (make-recatngle1 topleft bottomright)
(cons (topleft bottomright))

(define (make-rectangle2 topleft width height)
(cons (topleft
(make-point (+ (x-point topleft) width) (+ (y-point topleft) height)))

Остальное так же, как у вас в первом варианте представления. Теперь остальные функции для работы с прямоугльниками будут едиными, т.к. внутреннее представление одно, несмотря на то, что сконструировать его можно двумя способами.

Write a comment