- •4.9.1. Изменяемость
- •4.9.2. Классы операций
- •98 Глава 4
- •4.9.3. Полнота
- •100 Глава 4
- •4.9.5. Операции egual, similar и copy
- •102 Глава 4
- •104 Глава 4
- •5. Исключительные ситуации
- •108 Глава 5
- •110 Глава 5
- •6.2.1. Сигнализация об исключительных ситуациях
- •5.2.2. Обработка исключительных ситуаций
- •112 Глава 5
- •5.2.3. Предложение resignal
- •6.2.4. Необрабатываемые исключительные ситуации
- •114 Глава 5
- •6.2.3. Предложение resignal
- •5.2.4. Необрабатываемые исключительные ситуации
- •116 Глава 5
- •118 Глава 5
- •118 Глава 5
- •120 Глава 5
- •122 Глава 5
- •124 Глава 5
- •128 Глава 6
- •130 Глава 6
- •6.2.1. Реализация итераторов
- •6.2.2. Использование итераторов
- •132 Глава 6
- •134 Глава 6
- •136 Глава 6
- •138 Глава 6
- •140 Глава 7
- •142 Глава 7
- •7.2. Абстракция данных
- •144 Глава 7
- •146 Глава 7
- •148 Глава 7
- •150 Глава 7
- •7.4. Генераторы
- •162 Глава 7
- •154 Глава 7
- •156 Глава 7
- •162 Глава 8
- •164 Глава 8
- •166 Глава 8
- •168 Глава 8
- •170 Глава 9
- •172 Глава 9
- •174 Глава 9
- •176 Глава 9
- •9.1.3. Пример
- •178 Глава 9
- •180 Глава 9
- •182 Глава 9
- •184 Глава 9
- •186 Глава 9
- •188 Глава 9
- •190 Глава 9
- •192 Глава. 9
- •194 Глава 9
150 Глава 7
procedure q fetypeJ .append (q: queue [etype); e: etype); var )ast_elem, elem: queue [etype ]_rep; begin new (elem); elem+.val := e; elernT.next := nil; if q fetypeLisempty (q) then <\\ := elem else beiin ]ast_e]em := q^; while last_eleml•.next () nil do
last_elem := iast.eleml.next; last.elernf.next := elem end
end {процедура q [etypeLappend};
Рис. 7.7. Реализация процедуры q [etype]. append.
type intq s= •l•intq_гep; intq.rep == •l•intq_elem^ intq_elem = record val: ihteger; next: intq_rep; end;
procedure intq.append (q: intq; e: integer); var last_elem, elem; irftq.rep; begin new (elem); elem•r.val := e; elernf.next :=: nil; if intqJsempty (q) then •l' := elem else begin last_elem :== q•r,^ while last_elemf.next () nil do last_elem ;= last_elem•l•. next; last.elernf.next :== elem end
:• end {процедура intq.append};
Рис. 7.8. Конкретная реализация типа данных queue [etypel»
на integer, и надо изменить имена операций, заменив префикс, например переименовав q [etype Lappend в intq.append. На рис. 7.8 показана конкретная реализация объявления типа, взятого из рис. 7.8 g использованием реализации процедуры из рио. 7.7.
7.4. Генераторы
В языке Паскаль имеется оператор for, который позволяет выполнить итерацию в некотором поддиапазоне типов скалярных величин (за исключением типа real), но в нем совсем нет механизма для реализации итераторов, определенных пользователем.
.Использование языка Паскаль
Как отмечено в гл. 6, это может вызвать неудобства. Например, чтобы суммировать элементы в очереди целых чисел intqueue, мы могли бы написать программу, аналогичную программе, приведенной на рис. 7.9. Эта реализация была бы несколько менее неуклюжа, если бы мы к очереди целых чисел intqueue добавили функцию q.copy, но все равно она была бы неудовлетворительной. В этой программе имеются потери и по времени, и по пространству. По крайней мере они состоят из копирования всей очереди.
sum := О t := q.new; while not (qJsempty (q)) do
begin
i := q_remfirst (q); sum := sum + i; q_append (t, i) end;
while not (isempty (t)) do q_append (q, q_remfirst (t));
Рис. 7.9. Суммирование элементов очереди без использования итератора,
Чтобы избежать таких потерь, мы создадим тип некоторого специального вида, называемый генератором. Генераторы имитируют работу итераторов. У каждого генератора есть три функции и одна процедура. Эти три функции создают объект генератора, получают следующий элемент и проверяют, все ли элементы были выданы. Процедура уничтожает объект генератора.
Например, для очереди целых чисел мы могли бы создать генератор qelems. Функция qelems.create выполняет некоторую работу, которая соответствует той инициализации, которая делается до выполнения первого оператора yield в итераторе языка CLU. Эта функция возвращает некоторый объект с типом qelems. Вторая функция qelems_next выдает каждый раз один элемент при обращении к ней и модифицирует объект генератора qelems, чтобы указать, что этот элемент уже был выдан. Последняя функция qelems.done используется для определения того, были ли выданы все элементы. Процедура qelems, destroy освобождает пространство, которое было выделено при работе функций qe-lems.create и qelems_next.
Спецификация генератора qelems приведена на рис. 7.10. Обе функции qelems_done и qelems_next требуют, «чтобы очередь, используемая для создания элементов qi, не модифицировалась после того, как создан элемент qi». Это аналогично общему требованию предложения requires итераторов языка CLU, в которых требуется, чтобы объект, по которому совершается итерация, не модифицировался в теле данного цикла.
