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

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 Дисков Б,, Гатэг Дж.

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