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

25 February, 2008 (20:58) | Решения упражнений

Итак, мы хотим, чтобы внутреннее представление обычных чисел в нашей обобщенной системе совпадало со внутренним представлением чисел в Scheme. С числами в таком представлении работать удобнее, так как они выглядят естественнее.

Если мы вспомним, что процедуры attach-tag, type-tag и contents соответственно помечают данные типом, определяют тип данных и получают непомеченные данные из помеченных, то сразу же поймем, что для обычных чисел эти операции тривиальны:

  • помечать числа, как и договорились, мы вообще не будем;
  • определять тип будем с помощью предиката number?, а типом чисел будем считать scheme-number;
  • непомеченные числа у нас совпадают с помеченными.

Таким образом получим следующие определения введенных ранее процедур для работы с помеченными типом данными, в которых числа являются особым случаем:
(define (attach-tag type-tag contents)
  (if (number? contents)
      contents
      (cons type-tag contents)))

(define (type-tag datum)
  (cond ((number? datum) 'scheme-number)
        ((pair? datum) (car datum))
        (else (error "Некорректные помеченные данные -- TYPE-TAG" datum))))

(define (contents datum)
  (cond ((number? datum) datum)
        ((pair? datum) (cdr datum))
        (else (error "Некорректные помеченные данные -- CONTENTS" datum))))

А вот, хорошо ли это – иметь особые случаи – вопрос для отдельного обсуждения.

Comments

Comment from gorilych
Date: October 18, 2009, 6:19 pm

attach-tag некорректна. Если я придумаю новый тип, в котором содержание (contents) будет выражаться обычным числом, то она будет работать неправильно. Attach-tag вообще не должен анализировать contents. Анализироваться должен type-tag в данном случае. Если он совпадает с scheme-number, то возвращаться должен просто contents.

Comment from anonymous
Date: December 13, 2010, 1:49 pm

(define (attach-tag type-tag contents)
(if (eq? type-tag 'scheme-number)
contents
(cons type-tag contents)))

Comment from Максим
Date: December 21, 2014, 7:47 pm

gorilych, окей, а как вы собираетесь различать обычное число scheme-number представленное простым числом и ваше выдуманное, если у обоих не будет метки типа? То есть, (type-tag 1) возвращает scheme-number, а (type-tag 2) вашего нового типа будет что-то иное?

Comment from Максим
Date: December 21, 2014, 7:49 pm

gorilych, другими словами, вы видите возможность прописать два разных условия в процедуру type-tag для обычного числа?

Comment from Максим
Date: December 24, 2014, 3:51 pm

Правильная реализация (позволяет использовать все 4 типа – целочисленное, рациональное, вещественное, комплексное):

(define (contents datum)
(cond ((number? datum) datum)
((pair? datum) (cdr datum))
(else (error "Bad data"))))
(define (type-tag datum)
(cond ((number? datum) (if (exact? datum) 'integer 'real))
((pair? datum) (car datum))
(else (error "Bad data"))))
(define (attach-tag type-tag contents)
(if (number? contents)
contents
(cons type-tag contents)))

Comment from Den
Date: June 23, 2016, 8:17 am

Замечание gorilych’а совершенно верное. Процедура attach-tag должна анализировать type-tag, а не contents.

Write a comment