Решение упражнения 2.79 из SICP
Первым делом, определим саму обобщенную операцию проверки эквивалентности equ?. Мы еще не определяли обобщенных операций, являющихся предикатами. Но никаких сложностей с этим не возникает, ведь предикат – это всего лишь частный случай обыкновенной процедуры, который возвращает булево значение (истина или ложь). Таким образом определяется обобщенный предикат так же, как любая обобщенная операция:
(define (equ? x y) (apply-generic 'equ? x y))
Однако, есть важный нюанс. Поскольку возвращаемое значение имеет не пользовательский тип, а логический, нам не нужно добавлять к нему тег типа при определении в пакетах обыкновенных, рациональных и комплексных чисел.
Для того, чтобы реализовать equ? для каждого типа чисел, добавим в install-scheme-number-package следующий код:
(put 'equ? '(scheme-number scheme-number) =)
В install-rational-package аналогично добавим (процедура equal-rat? взята один в один из раздела 2.1.1 без модификаций):
(define (equal-rat? x y)
(= (* (numer x) (denom y))
(* (numer y) (denom x))))
(put 'equ? '(rational rational) equal-rat?)
В install-complex-package добавим такие строки:
(define (equal-complex? x y)
(and (= (real-part x) (real-part y))
(= (imag-part x) (imag-part y))))
(put 'equ? '(complex complex) equal-complex?)
Все. Теперь наша обобщенная операция equ? будет работать при сравнении пар обыкновенных, рациональных либо действительных чисел. Правда, сравнить обыкновенный 0 с рациональным 0/1 или комплексным 0+0i не получится. Пока что. Следующий раздел книги 2.5.2 как раз об этом…
Comments
Pingback from SICP по-русски » Решение упражнения 2.80 из SICP
Date: February 26, 2008, 10:58 pm
[…] упражнение аналогично предыдущему, поэтому буду краток, но остановлюсь на интересных […]
Write a comment