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

134 Глава 6

примером рис. 6.9:

является итератор permuta-

node== record [val: t, left, right: olist [t]] rep = variant [some: node, empty: null] small _to_big= Her (s: cvt) yields (t) tagcase s tag empty: return tag some (n: node): for e; t in small_to_big (n.left) do % выдать элементы левого поддерева yield (e) end yield (n.val) for e: t in small_to_big (n.right) do % выдать элементы правого поддерева yield (e) end end end small_to_big Рис. 6.8. Операция small, to_ big для упорядоченного списка.

Нашим следующим tions, приведенный на

si = sequence (int) permutations = iter (seq: si) yields (si)

% если последовательность состоит из одного числа, то оно выдается, и ор­ганизуется выход if si$size (seq) = I then yield (seq) else for index: int in si$indexes (seq) do % Создать некоторую последовательность, в которой опущено значение

с этим индексом val: int;=seq [index] prefix: si :== si$subseq (seq, I, index — 1) suffix: si :=si$subseq (seq, index+ I, si$size (seq)) % Присоединить перестановки последовательности к этому значению

и выдать

for perm: si in permutations (prefix Ц suffix) do % Операция II является операцией конкатенации yield (si$addl (perm, val)) end % конец для perm end % конец для index end % конец для if end permutations Рис. 6.9. Итератор permutations.

permutations' iter (seq: sequence [int]) yields (sequence [int]) effects Выдает в произвольном порядке все последовательности, по­строенные при помощи перестановок элементов в наборе seq.

Данная реализация использует итератор последовательностей indexes. При работе этот итератор выдает все перестановки, кото­рые получаются, если зафиксировать на первом месте первый элемент первоначальной последовательности, затем зафиксиро­вать на первом месте второй элемент первоначальной последова­тельности и т. д. Для того чтобы получить перестановки с зафик­сированным на первом месте п-ным элементом, создается некото­рая последовательность, содержащая все другие элементы, и

\ракция итерации

_полняются перестановки этой последовательности, обращаясь рекурсивно к самому себе. Затем п-ный элемент добавляется ^ к началу каждой перестановки последовательности и выдается результирующая последовательность.

Нашим последним примером является итератор allprimes, приведенный на рис. 6.10.

ai = array [int] allprimes = iter ( ) yields (int) yield (2) % выдается первое простое число primes: ai :== ai$new ( ) x: int := I while true do

x: = x+2 % следующее рассматриваемое число for p: int in ai$elements (primes) do if x//p == 0 then exit not_found end

% x—не простое число

if piiip^x then break end % x — простое число end except when not_found: continue end % имеем некоторое простое число yield (x) ai$addh (primes, x) end end primes Рис. 6.10. Итератор allprimes.

allprimes =: iter ( ) yields (int) effects Выдаются простые числа в возрастающем порядке.

В нашей реализации все найденные до некоторого момента простые числа Хранятся в массиве primes. В цикле while полу­чаются нечетные числа. Те из них, которые кратны ранее найден­ным простым числам, отбрасываются в цикле for. Мы останавли­ваем цикл for, как только достигаем некоторого простого числа, чей квадрат больше текущего рассматриваемого числа, поскольку это рассматриваемое число не может, по-видимому, делиться на большее простое число.

6.4. Вопросы проектирования

Итераторы будут включаться среди других операций в боль­шинство типов данных, особенно в такие типы, как intset и olist, чьи объекты являются совокупностями других объектов. Итера­торы часто необходимы для полноты — они позволяют органи­зовать доступ к элементам некоторой совокупности таким спосо­бом, который эффективен и удобен.

Тип может иметь несколько итераторов. Например, упорядо­ченные списки olist могли бы иметь такую операцию:

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

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