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


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




[43]

Операции высших порядков

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

Например, и flipped-pairs, и square-limit располагают определенным образом в виде квадрата четыре копии порождаемого рисовалкой изображения; они отличаются только тем, как они ориентируют эти копии. Один из способов абстрагировать такую схему комбинирования рисовалок представлен следующей процедурой, которая принимает четыре одноаргументных операции и порождает операцию над рисовалками, которая трансформирует данную ей рисовалку с помощью этих четырех операций и расставляет результаты по квадрату. Tl, tr, bl и br - это трансформации, которые следует применить к верхней левой, верхней правой, нижней левой и нижней правой копиям, соответственно.

(define (square-of-four tl tr bl br) (lambda (painter)

(let ((top (beside (tl painter) (tr painter)))

(bottom (beside (bl painter) (br painter)))) (below bottom top))))

Тогда в терминах square-of-four можно определить flipped-pairs следующим образом:24

(define (flipped-pairs painter)

(let ((combine4 (square-of-four identity flip-vert

identity flip-vert)))

(combine4 painter)))

а square-limit можно выразить как25

(define (square-limit painter n)

(let ((combine4 (square-of-four flip-horiz identity

rotate180 flip-vert))) (combine4 (corner-split painter n))))

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

Right-split и up-split можно выразить как разновидности общей операции разделения. Определите процедуру split с таким свойством, что вычисление

(define right-split (split beside below)) (define up-split (split below beside))

порождает процедуры right-split и up-split с таким же поведением, как и определенные ранее.

24 Мы также могли бы написать

(define flipped-pairs

(square-of-four identity flip-vert identity flip-vert))

25Rotate180 поворачивает рисовалку на 180 градусов (см. упражнение 2.50). Вместо rotate180 мы могли бы сказать (compose flip-vert flip-horiz) , используя процедуру compose из упражнения 1.42.


вектор edge2

рамки

вектор edge1

рамки

вектор origin

рамки

Точка (0,0) на экране

Рис. 2.15: Рамка представляется в виде трех векторов двух краев.

начальной точки и

Рамки

Прежде, чем мы сможем показать, как реализуются рисовалки и средства их комбинирования, нам нужно рассмотреть рамки. Рамку можно описать как три вектора - вектор исходной точки и два вектора краев рамки. Вектор исходной точки Origin указывает смещение исходной точки рамки от некой абсолютной начальной точки, а векторы краев Edget и Edge2 указывают смещение углов рамки от ее исходной точки. Если края перпендикулярны, рамка будет прямоугольной. В противном случае рамка будет представлять более общий случай параллелограмма. На рис. 2.15 показаны рамка и соответствующие ей вектора. В соответствии с принципами абстракции данных, нам пока незачем указывать, каким образом представляются рамки; нужно только сказать, что есть конструктор make-frame, который принимает три вектора и выдает рамку, и что есть еще три селектора, origin-frame, edge1-frame и edge2-frame (см. упражнение 2.47).

Для определения изображений мы будем использовать координаты в единичном квадрате (0 < x,y < 1). Каждой рамке мы сопоставляем отображение координат рамки (frame coordinate map), которое будет использоваться, чтобы сдвигать и масштабировать изображения так, чтобы они умещались в рамку. Это отображение трансформирует единичный квадрат в рамку, переводя вектор v = (x,y) в сумму векторов

Origin(Frame) + x • Edgex (Frame) + y • Edge2(Frame)

Например, (0, 0) отображается в исходную точку рамки, (1, 1) в вершину, противоположную исходной точке по диагонали, а (0.5, 0.5) в центр рамки. Мы можем создать отображение координат рамки при помощи следующей процеду-ры:26

26Frame-coord-map использует векторные операции, определенные ниже в упражнении 2.46, и мы предполагаем, что они реализованы для какого-нибудь представления векторов. Благодаря абстракции данных, неважно, каково это представление; нужно только, чтобы операции над векторами вели себя правильно.


(define (frame-coord-map frame) (lambda (v) (add-vect (origin-frame frame) (add-vect (scale-vect (xcor-vect v)

(edge1-frame frame)) (scale-vect (ycor-vect v)

(edge2-frame frame))))))

Заметим, что применение frame-coord-map к рамке дает нам процедуру, которая, получая вектор, возвращает тоже вектор. Если вектор-аргумент находится в единичном квадрате, вектор-результат окажется в рамке. Например,

((frame-coord-map a-frame) (make-vect 0 0))

возвращает тот же вектор, что и

(origin-frame a-frame)

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

Двумерный вектор v, идущий от начала координат к точке, можно представить в виде пары, состоящей из x-координаты и y-координаты. Реализуйте абстракцию данных для векторов, написав конструктор make-vect и соответствующие селекторы xcor-vect и ycor-vect. В терминах своих селекторов и конструктора реализуйте процедуры add-vect, sub-vect и scale-vect, которые выполняют операции сложения, вычитания векторов и умножения вектора на скаляр:

(Х1 ,У1) + (Х2 ,У2 ) = (Х1 + Х2 ,У1 + Jft) (Х1, yi) - (Х2, У2) = (Х1 - Х2, yi - Jft)

s • (х, y) = (sx, sy)

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

Вот два варианта конструкторов для рамок:

(define (make-frame origin edge1 edge2) (list origin edge1 edge2))

(define (make-frame origin edge1 edge2) (cons origin (cons edge1 edge2)))

К каждому из этих конструкторов добавьте соответствующие селекторы, так, чтобы получить реализацию рамок.

Рисовалки

Рисовалка представляется в виде процедуры, которая, получая в качестве аргумента рамку, рисует определенное изображение, отмасштабированное и сдвинутое так, чтобы уместиться в эту рамку. Это означает, что если есть рисовалка p и рамка f, то мы можем получить изображение, порождаемое p, в f, позвав p с f в качестве аргумента.

Детали того, как реализуются элементарные рисовалки, зависят от конкретных характеристик графической системы и типа изображения, которое надо получить. Например, пусть у нас будет процедура draw-line, которая рисует на



[стр.Начало] [стр.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]