Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Скачиваний:
45
Добавлен:
23.03.2015
Размер:
884 Кб
Скачать

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, в которых требуется, чтобы объект, по которому совершается итерация, не модифицировался в теле данного цикла.

Соседние файлы в папке POSIBNIK