- •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
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 показана некоторая реализация итератора •elements для наборов 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
