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

26 February, 2008 (22:30) | Решения упражнений

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

Обобщенная процедура =zero? определяется следующим типичным образом:
(define (=zero? x) (apply-generic '=zero? x))

В пакет для работы с обычными числами добавляем строки:

(define (=zero? x) (= x 0)) 
(put '=zero? '(scheme-number) =zero?)

В пакет рациональных чисел добавляем:

(define (=zero? x) (= (numer x) 0)) 
(put '=zero? '(rational) =zero?)

В пакет комплексных чисел включаем строки:

(define (=zero? x) 
  (and (= (real-part x) 0) 
       (= (imag-part x) 0))) 
(put '=zero? '(complex) =zero?)

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

С другой стороны, мы могли бы захотеть использовать при реализации проверки на ноль для рациональных и комплексных чисел уже реализованную проверку на ноль для обычных чисел. В таком случае нам бы понадобилось бы иметь доступ к обобщенной операции внутри специфичной операции пакета. В этом случае процедуры следовало бы назвать по-разному.

Еще один способ определения внутренних процедур – помещать их как безымянные lambda-опредления прямо внутрь put.

Я продемонстрирую кратко совмещение последних двух подходов:

;install-scheme-number-package: 
(put '=zero? 
     '(scheme-number) 
     (lambda (x) (= x 0)))
;install-rational-package: 
(put '=zero? 
     '(rational) 
     (lambda (x) (=zero? (numer x))))
;install-complex-package: 
(put '=zero? 
     '(complex) 
     (lambda (x) (and (=zero? (real-part x)) 
                      (=zero? (imag-part x)))))

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

Comments

Comment from Dima
Date: September 2, 2008, 10:41 pm

Можно также:

(put '=zero? '(complex)
(lambda (x) (= 0 (magnitude x))))

Write a comment