- •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
128 Глава 6
Абстракция итерации
stblim == proc (s: intset) returns (iit) items: sequence [int] :== intset$el_seg(s) i: int :-= I sum: int := 0 while true do sum :== sum+ items [i]
except when bounds: return (srum) end i:=i+ I end end setsum
Рис. 6.2. Реализация процедуры setsum с использованием операции eLseg.
проверять все элементы множества, в котором организуется поиск. Например, если бы мы организовали в наборе intset поиск некоторого отрицательного элемента, то могли остановиться тогда, когда встретили бы первый отрицательный элемент. Однако, мы должны обработать все элементы множества, чтобы построить последовательность.
Некоторой альтернативой для операции eLseg является операция, которая просто выдает массив представления. Однако это решение является очень плохим, поскольку оно уничтожает абстракцию через спецификацию. Мы в действительности внесли операцию down и потеряли локальный контроль над представлением.
Требуется некоторый общий метод итерации, который удобен и эффективен и который сохраняет абстракцию через спецификацию. Итератор обеспечивает эти требования. Он вызывается как 1 процедура, но вместо окончания с выдачей всех результатов цмеет 1 много результатов, которые выдает каждый раз по одному. Порученные элементы могут использоваться в других модулях, которые задают действия, выполняемые для каждого такого элемента. Использующий итератор модуль будет содержать некоторую структуру организации цикла, например, такую:
for each для элемента результата i, выданного итератором А do выполнить над i некоторое действие
Каждый раз, когда итератор выдает некоторый элемент, над этим элементом выполняется тело цикла. Затем управление возвращается в итератор, так что он может выдавать следующий элемент.
Отметим разделение обязанностей в такой форме. Итератор ответствен за получение элемента, а модуль, содержащий цикл, определяет то действие, которое будет над ним выполняться. Итератор может использоваться в различных модулях, которые выполняют разные действия над элементами, и он может быть реализован различными способами, не оказывая влияния на эти модули.
Поскольку итератор выдает элементы по одному, исчезают проблемы пространства и времени, упоминавшиеся ранее. Нам не нужно строить потенциально большую структуру данных, которая содержит такие элементы. Более того, если модуль выполняет некоторый цикл поиска, итератор может быть остановлен, как только будет найден интересующий его элемент.
Как упоминалось ранее, итераторы являются некоторой обобщенной формой методов итерации, имеющихся в большинстве языков программирования, В дополнение к некоторой форме цикла «while» языки программирования обычно имеют некоторую конструкцию «for» для итерации по целым числам. Такая итерация полезна при обработке массивов, которые индексируются, но она неудобна для таких неиндексируемых абстракций, как наборы itset.
(•» 6.1. Спецификация
'. ' Как и другие абстракции, итераторы должны быть определены через спецификации. Форма спецификации итерации аналогична форме для процедуры. Заголовок имеет такой вид:
iname = iter (...) yields (...) signals (...)
Здесь мы используем ключевое слово iter для обозначения абстракции итератора. Итератор может совсем не выдавать объектов на каждой итерации или выдать несколько объектов. Число и тип этих объектов описываются в предложении yields. (Если для каждого yields не выдается ни одного объекта, то предложение yields может быть опущено.) Итератор может не выдавать никаких результатов, когда он заканчивается нормально, но он может заканчиваться по исключительной ситуации с именем и результатами, указанными в предложении signals. Например,
elements = iter (s: intset) yields (int) requires s не модифицируется в теле цикла.
effects Выдает элементы s в некотором произвольно?л порядке, причем каждый элемент только один раз.
Эта операция вполне правдоподобна для набора intset. Отметим, что операция elements не имеет исключительных ситуаций. Если ей будет задан в качестве аргумента пустой набор intset, она просто заканчивается, не выдавая ни одного элемента. Характерно, что использование итераторов исключает проблемы, связанные с заданием некоторых аргументов (таких, как пустой набор intset) для соответствующих процедур (таких, как процедура choose).
Мы требуем, чтобы набор s не модифицировался при использовании цикла. Подобные ограничения типичны для итераторов 5 Дисков Б,, Гатэг Дж.
