Решение упражнения 2.80 из SICP
Это упражнение аналогично предыдущему, поэтому буду краток, но остановлюсь на интересных деталях.
Обобщенная процедура =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