Ремонт принтеров, сканнеров, факсов и остальной офисной техники


назад Оглавление вперед




[59]

(lambda (x y) (tag (- x y)))) (put mul (scheme-number scheme-number)

(lambda (x y) (tag (* x y)))) (put div (scheme-number scheme-number)

(lambda (x y) (tag (/ x y)))) (put make scheme-number

(lambda (x) (tag x))) done)

Пользователи пакета Схемных чисел будут создавать (помеченные) элементарные числа с помощью процедуры

(define (make-scheme-number n) ((get make scheme-number) n))

Теперь, когда каркас обобщенной арифметической системы построен, мы можем без труда добавлять новые типы чисел. Вот пакет, который реализует арифметику рациональных чисел. Обратите внимание, что благодаря аддитивности мы можем без изменений использовать код рациональной арифметики из раздела 2.1.1 в виде внутренних процедур пакета:

(define (install-rational-package) ;; внутренние процедуры (define (numer x) (car x)) (define (denom x) (cdr x)) (define (make-rat n d)

(let ((g (gcd n d))) (cons (/ n g) (/ d g))))

(define (add-rat x y)

(make-rat (+ (* (numer x) (denom y)) (* (numer y) (denom x))) (* (denom x) (denom y)))) (define (sub-rat x y)

(make-rat (- (* (numer x) (denom y)) (* (numer y) (denom x))) (* (denom x) (denom y)))) (define (mul-rat x y)

(make-rat (* (numer x) (numer y))

(* (denom x) (denom y)))) (define (div-rat x y)

(make-rat (* (numer x) (denom y))

(* (denom x) (numer y)))) ;; интерфейс к остальной системе (define (tag x) (attach-tag rational x)) (put add (rational rational)

(lambda (x y) (tag (add-rat x y)))) (put sub (rational rational)

(lambda (x y) (tag (sub-rat x y)))) (put mul (rational rational)

(lambda (x y) (tag (mul-rat x y)))) (put div (rational rational)

(lambda (x y) (tag (div-rat x y))))

(put make rational


(lambda (n d) (tag (make-rat n d)))) done)

(define (make-rational n d) ((get make rational) n d))

Мы можем установить подобный пакет и для комплексных чисел, используя метку complex. При создании пакета мы извлекаем из таблицы операции make-from-real-imag и make-from-mag-ang, определенные в декартовом и полярном пакетах. Аддитивность позволяет нам использовать без изменений в качестве внутренних операций процедуры add-complex, sub-complex, mul-complex и div-complex из раздела 2.4.1.

(define (install-complex-package)

;; процедуры, импортируемые из декартова ;; и полярного пакетов (define (make-from-real-imag x y)

((get make-from-real-imag rectangular) x y)) (define (make-from-mag-ang r a)

((get make-from-mag-ang polar) r a)) ;; внутренние процедуры (define (add-complex zl z2)

(make-from-real-imag (+ (real-part zl)

(+ (imag-part zl) (define (sub-complex z1 z2)

(make-from-real-imag (- (real-part zl)

(- (imag-part zl)

(define (mul-complex (make-from-mag-ang

(real-part (imag-part

(real-part (imag-part

z2)) z2))))

z2)) z2))))

(define (div-complex (make-from-mag-ang

zl

(+ zl

(-

z2)

(magnitude (angle zl)

z2)

(magnitude (angle zl)

zl) (magnitude z2))

(angle z2))))

zl) (magnitude z2))

(angle z2))))

;; интерфейс к остальной системе (define (tag z) (attach-tag complex z)) (put add (complex complex)

(lambda (zl z2) (tag (add-complex zl z2)))) (put sub (complex complex)

(lambda (zl z2) (tag (sub-complex zl z2)))) (put mul (complex complex)

(lambda (zl z2) (tag (mul-complex zl z2)))) (put div (complex complex)

(lambda (zl z2) (tag (div-complex zl z2)))) (put make-from-real-imag complex

(lambda (x y) (tag (make-from-real-imag x y)))) (put make-from-mag-ang complex

(lambda (r a) (tag (make-from-mag-ang r a)))) done)

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


complex rectangular

3 4

Рис. 2.24: Представление 3 + 4i в декартовой форме.

(define (make-complex-from-real-imag x y) ((get make-from-real-imag complex) x y))

(define (make-complex-from-mag-ang r a) ((get make-from-mag-ang complex) r a))

Здесь мы имеем двухуровневую систему меток. Типичное комплексное число, например 3 + 4i в декартовой форме, будет представлено так, как показано на рисунке 2.24. Внешняя метка (complex) используется, чтобы отнести число к пакету комплексных чисел. Внутри комплексного пакета вторая метка (rectangular) относит число к декартову пакету. В большой и сложной системе может быть несколько уровней, каждый из которых связан со следующим при помощи обобщенных операций. Когда объект данных передается «вниз», внешняя метка, которая используется для отнесения к нужному пакету, отрывается (при помощи вызова contents), и следующий уровень меток (если таковой имеется) становится доступным для дальнейшей диспетчеризации.

В приведенных пакетах мы использовали add-rat, add-complex и другие арифметические процедуры ровно в таком виде, как они были написаны с самого начала. Но когда эти определения оказываются внутри различных процедур установки, отпадает необходимость давать им различные имена: мы могли бы просто назвать их в обоих пакетах add, sub, mul и div.

Упражнение 2.77.

Хьюго Дум пытается вычислить выражение (magnitude z), где z - объект, показанный на рис.2.24. К своему удивлению, вместо ответа 5 он получает сообщение об ошибке от apply-generic, гласящее, что у операции magnitude нет методов для типа (complex). Он показывает результат Лизе П. Хакер. Та заявляет: "Дело в том, что селекторы комплексных чисел для чисел с меткой complex определены не были, а были только для чисел с меткой polar и rectangular. Все, что требуется, чтобы заставить это работать - это добавить к пакету complex следующее:"

(put real-part (complex) real-part) (put imag-part (complex) imag-part) (put magnitude (complex) magnitude) (put angle (complex) angle)

Подробно опишите, почему это работает. В качестве примера, проследите все процедуры, которые вызываются при вычислении (magnitude z) , где z - объект, показанный на рис.2.24. В частности, сколько раз вызывается apply-generic? На какую процедуру она диспетчирует в каждом случае?

Упражнение 2.78.

В пакете scheme-number внутренние процедуры, в сущности, ничего не делают, только вызывают элементарные процедуры +, -, и т.д. Прямо использовать примитивы языка



[стр.Начало] [стр.1] [стр.2] [стр.3] [стр.4] [стр.5] [стр.6] [стр.7] [стр.8] [стр.9] [стр.10] [стр.11] [стр.12] [стр.13] [стр.14] [стр.15] [стр.16] [стр.17] [стр.18] [стр.19] [стр.20] [стр.21] [стр.22] [стр.23] [стр.24] [стр.25] [стр.26] [стр.27] [стр.28] [стр.29] [стр.30] [стр.31] [стр.32] [стр.33] [стр.34] [стр.35] [стр.36] [стр.37] [стр.38] [стр.39] [стр.40] [стр.41] [стр.42] [стр.43] [стр.44] [стр.45] [стр.46] [стр.47] [стр.48] [стр.49] [стр.50] [стр.51] [стр.52] [стр.53] [стр.54] [стр.55] [стр.56] [стр.57] [стр.58] [стр.59] [стр.60] [стр.61] [стр.62] [стр.63] [стр.64] [стр.65] [стр.66] [стр.67] [стр.68] [стр.69] [стр.70] [стр.71] [стр.72] [стр.73] [стр.74] [стр.75] [стр.76] [стр.77] [стр.78] [стр.79] [стр.80] [стр.81] [стр.82] [стр.83] [стр.84] [стр.85] [стр.86] [стр.87] [стр.88] [стр.89] [стр.90] [стр.91] [стр.92] [стр.93] [стр.94] [стр.95] [стр.96] [стр.97] [стр.98] [стр.99] [стр.100] [стр.101] [стр.102] [стр.103] [стр.104] [стр.105] [стр.106] [стр.107] [стр.108] [стр.109] [стр.110] [стр.111] [стр.112] [стр.113] [стр.114] [стр.115] [стр.116] [стр.117] [стр.118] [стр.119] [стр.120] [стр.121] [стр.122] [стр.123] [стр.124] [стр.125] [стр.126] [стр.127] [стр.128] [стр.129] [стр.130] [стр.131] [стр.132] [стр.133] [стр.134] [стр.135] [стр.136] [стр.137] [стр.138] [стр.139] [стр.140] [стр.141] [стр.142] [стр.143] [стр.144] [стр.145] [стр.146] [стр.147] [стр.148] [стр.149] [стр.150] [стр.151] [стр.152] [стр.153] [стр.154] [стр.155] [стр.156] [стр.157] [стр.158] [стр.159] [стр.160] [стр.161] [стр.162] [стр.163] [стр.164] [стр.165] [стр.166] [стр.167] [стр.168] [стр.169] [стр.170] [стр.171] [стр.172] [стр.173] [стр.174] [стр.175] [стр.176] [стр.177] [стр.178] [стр.179] [стр.180] [стр.181] [стр.182] [стр.183] [стр.184] [стр.185] [стр.186] [стр.187] [стр.188] [стр.189] [стр.190] [стр.191] [стр.192] [стр.193] [стр.194] [стр.195] [стр.196]