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

130 Глава 6

Абстракция итерации

которые работают над такими изменяемыми объектами, как наборы intset, поскольку тогда станет неясно, что такое «элементы набора 8».'Эти ограничения будут еще обсуждаться в разд. 6.4.

6.2. Итераторы языка CLU

Итераторы могут быть реализованы в языке программирова­ния CLU при помощи модуля iter. Итераторы могут также исполь-аовать оператор for, имеющийся в языке CLU.

6.2.1. Реализация итераторов

Конструкция iter языка CLU аналогична конструкции proo. Она имеет заголовок, похожий на заголовок спецификации итера­тора. В теле этой конструкции для получения следующего эле­мента используется предложение yield. Однако выполнение опе­рации iter на этом не закапчивается. Наоборот, она готова вы­давать дополнительные элементы, если вызвавшая ее процедура в этом заинтересована, В этом случае она продолжает свое выпол­нение с предложения, следующего за предложением yield, а ее локальные переменные имеют те же самые значения, как и до выполнения предложения yield.

На рис. 6.3 показана некоторая реализация итератора •ele­ments для наборов intset. Здесь мы предполагаем, что массивы представляются в том же виде, как и на рис. 4.5 и 5.5. Когда операция elements продолжает свое выполнение после предложе­ния yield, ее переменная i является индексом выданного перед этим элемента. Операция elements затем продолжает работать и выдает следующий элемент, а заканчивает работу тогда, когда будут выданы все элементы.

гер == array [int.] elements == iter (s: cvt) yields (int) i; int :== rep$low (s) while true do yield (s fi])

except when bounds: return end i := i + I end end elements Рис. 6.3. Операция elements в наборе intset.

6.2.2. Использование итераторов

Для итераторов можно использовать оператор for, имеющийся в языке CLU. Этот оператор определяет некоторые переменные цикла. Если эти переменные являются локальными для цикла, форма такого оператора следующая:

for deeLlist in iter.call do body end

Если переменные не являются локальными, то используется такая форма:

for idn_list in iter. call do body end

Когда оператор for начинает свое выполнение, создаются, если необходимо, переменные цикла и выполняется операция iter_call. Когда итератор выдает элемент, выданные объекты за­писываются в переменные цикла и затем выполняется тело цикла. Когда тело цикла выполняется, управление передается назад в итератор. Когда итератор закончит работу, цикл for также заканчивает работу и управление в использующей эту конструк­цию программе передается на оператор, следующий за операто­ром for. Кроме этого, если в теле цикла выполнится некоторый оператор, который завершит выполнение оператора for, то ите­ратор автоматически завершит свою работу.

На рис. 6.4 показана третья реализация процедуры setsum. Каждый раз, когда выполняется тело цикла, в переменную цикла е устанавливается другой элемент данного набора. Этот элемент добавляется в переменную sum, и затем тело цикла заканчивается, вызывая продолжение выполнения итератора. Когда будут вы­даны все элементы, операция elements завершается и вызывает окончание работы оператора for. Затем процедура setsum выдает вычисленную сумму.

setsum == proc (s: intset) returns (int) sum; int :== 0 for е: int in intset$elements (s) do sum := sum + jg_ end return (sum) end setsum

Рис. 6.4. Использование итератора.

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

На рис. 6.5 показана трассировка выполнения процедуры sum е i рс В setsum рс В elements

После первой выдачи После второй выдачи После третьей выдачи Окончание

О

4

5 12

начало тела начало тела начало тела оператор return

Рис. 6.5. Трассировка выполнения процедуры setsum.

после yield после yield после yield

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