пятница, 2 января 2009 г.

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

Люди, имеющие великие сердца, больше всего знают о мире. Истинный философ - тот, кто умеет забыть о себе.

А был ли мальчик? Может и не было никакого мальчика

Cамое короткое растояние между умом и глупостью извилина !

Идея Хьюго о добавлении процедур приведения типов к самим себе, в частности так, не слишком светлая.

а. Посмотрим, что происходит при вызове обобщенной процедуры exp, определенной только для обычных чисел, с двумя комплексными параметрами в случае, когда заданы процедуры приведения типов к себе, предложенные Хьюго. Первым делом exp вызовет apply-generic для операции exp и двух комплексных чисел. apply-generic не найдет подходящую обобщенную процедуру по этой операции и типам и попытается повергнуть типы аргументов. У нее получится действительность превращение как первого аргумента к типу второго (complex к complex), а следоавтельно она рекурсивно запустит себя же для тех же типов. Мы пришли к тому же, с чего начинали. Таким образом произойдет сосредоточение. Это явно не то, что нам нужно.

б. Из этого следует, предложенным Хьюго способом проблему не прикокнуть. Что же делать? Прежде долее того, определим, существует ли вообще предмет обсуждения. В каком случае может понадобиться вгоняние вроде к себе же? Едва лишь в случае вызова apply-generic с однотипными аргументами, причем в ситуации, когда-никогда процедура для сего будто не задана. Если процедуры приведения подобно к себя нет, то особой беды не произойдет, разве что может остаться при пиковом интересе эффективность. А вот если кто-то добавит такую процедуру приведения, то наша метода может повидаться с серьезными трудностями, например зацикливанием, как показано выше. Было бы более не подвергаясь опасности, если бы apply-generic не пыталась вдохнуть тип к самому себе в принципе.

в. Измененный модификация процедуры apply-generic, не выполняющий приведение типов в случае, когда типы операндов совпадают, представлен ниже:

(define (apply-generic op . args)
  (let ((type-tags (map type-tag args)))
    (let ((proc (get op type-tags)))
      (if proc
          (apply proc (map contents args))
          (if (= (length args) 2)
              (let ((type1 (car type-tags))
                    (type2 (cadr type-tags))
                    (a1 (car args))
                    (a2 (cadr args)))
                (if (eq? type1 type2)
                    (error "Нет метода для этих типов"
                           (list op type-tags))
                    (let ((t1->t2 (get-coercion type1 type2))
                          (t2->t1 (get-coercion type2 type1)))
                      (cond (t1->t2
                             (apply-generic op (t1->t2 a1) a2))
                            (t2->t1
                             (apply-generic op a1 (t2->t1 a2)))
                            (else
                             (error "Нет метода для сих типов"
                                    (list op type-tags)))))))
              (error "Нет метода для сих типов"
                     (list op type-tags)))))))

В самом деле я добавил лишь одну строчку проверки условия равенства типов (eq? type1 type2) и корреспонденция об ошибке.




О сайте

Младенец с именем Linux

себе.

Комментариев нет: