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

132 Глава 6

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

setsum, когда к ней обращаются с набором intset jl, 4, 71, пред­полагая, что представляющий этот набор массив содержит эти элементы в порядке 4, 1, 7, На этом рисунке показаны значения локальных в процедуре setsum переменных sum и е и локальной в операции elements переменной i сразу же после выдачи элемента. Показано также значение переменной sum после окончания цикла в процедуре setsum. В этом случае значения переменных i и е не показаны, поскольку обращение к операции elements и тело цикла завершилось. После выдачи каждого элемента счетчик команд (рс) в процедуре setsum находится в начале тела опера­тора for, а счетчик команд для операции elements находится на операторе, следующем за оператором yield, г. е. на операторе присваивания для переменной i.

На рис. 6.6 показан второй пример использования операции elements — поиск некоторого отрицательного элемента. Если вы­данный элемент отрицателен, то процедура find. neg сразу же выдает результат. При этом возврате оператор for, а значит, и операция elements завершают работу до того, как будут выданы другие целые числа в наборе intset.

find.neg= pi-ос (s: intset) returns (int) signal (notJouiid) for x: int in intsel$e!ernents (s) do if x < 0 then return (x) end er.d signal not „found end find.neg

Рис. 6.6. Использование итератора для поиска.

К итераторам можно обращаться только из операторов for, и из каждого оператора for можно обращаться только к одному итератору. Однако операторы for могут быть вложенными. Кроме того, итераторы могут быть реализованы при помощи операторов for и их реализация может быть рекурсивной. Некоторые такие примеры приводятся в разд. 6.3.

6.2.3. Встроенные итераторы

В языке CLU имеется ряд операций итераторов для встроен­ных типов. Для целых чисел имеется операция intSfrom.to,

from. to == iter(x, у: int) yields (int)

effects Выдает целые числа между x и у включительно в порядке следо­вания.

Имеется также операция int$from_to.by, чей третий аргумент задает величину, на которую увеличивается переменная х на каждой итерации. Для массивов (и последовательностей) имеется два итератора — операция elements, которая выдает элементы массива (или последовательности) от нижней границы до верхней

границы, и операция indexes, которая выдает индексы массива (или последовательности) от нижней границы до верхней границы. И наконец, строки имеют итератор chars, который выдает символы строки от первого до последнего.

Примеры

В этом разделе приводится несколько примеров итераторов. Первый пример, приведенный на рис. 6.7, — это простой «фильтр». Он называется фильтром потому, что удаляет некоторые элементы, выданные другим итератором, и выдает только остальные эле­менты в процедуру, которая к нему обращается.

filter = iter (s: intset, els: itertype (intset) yields (int),

pred: proctype (int) returns (bool)) yields (int) requires чтобы s не модифицировался в теле цикла. effects Выдает в произвольном порядке все элементы, выданные опе­рацией els (s), которые удовлетворяют условию, заданному в pred',

iter (s: intset, els: itertype (intset) yields (int),

pred: proctype (int) returns (bool)) yields (iiit) for е: int in els (s) do if pred (e) then yield (е) end end end filter

Рис. 6.7. Фильтр.

Например, если операция odd выдает значение true, только если ее целый аргумент является нечетным числом, то фильтр

filter (s, intset^elements, odd)

выдает нечетные числа из набора s. В качестве второго примера добавим операцию

smalLto.big к упорядоченному списку olist.

small_to.big= iter (s, olist [t]) yields (t) requires чтобы набор s не модифицировался в теле цикла. effects Выдает элементы набора s в возрастающем порядке, определяемом при помощи операции t$lt, причем каждый элемент только один раз.

Эта операция могла бы заменить операцию least, описанную ранее. Реализация показана на рис. 6.8. Она рекурсивна — сперва операция small, to_big обращается рекурсивно сама к себе для любого поддерева, затем она выдает значение в узле, и далее она обращается рекурсивно сама к себе для правого поддерева. Заметим, между прочим, что операция smalLto_big является некоторой абстракцией через параметризацию. Она наследует тип параметра t из упорядоченного списка olist.

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