1.9. ИТЕРАТИВНЫЕ ЦИКЛЫ

Основным средством изображения циклов в Рефале Плюс являются рекурсивные определения функций. Во многих случаях, однако, это средство оказывается слишком универсальным. Поэтому в Рефале Плюс предусмотрена конструкция поиска, которая имеет следующий вид:

S" $iter S' :: He R

и синтаксически является тропой. При этом, источники S" и S' являются суверенами, а хвост R - вассалом (что существенно, если они содержат правые части вида = Q ).

Если хвост R состоит из одной запятой, его разрешается опускать. Также, если жесткое выражение He - пустое, его разрешается опускать вместе с ключевым словом "::". Тропа-поиск вводит новые локальные переменные (так же, как и тропа-присваивание S :: He R ). Начальные значения этих переменных получаются путем вычисления источника S". Затем делается попытка вычислить хвост R. Если она завершается успешно, то полученный результат считается результатом всей конструкции. Если же вычисление хвоста R кончается неуспехом, то вычисляются новые значения для переменных, входящих в He (для этого вычисляется источник S', причем для этого используются старые значения переменных). Далее делается новая попытка вычислить хвост R и т.д.

Таким образом, тропа-поиск как бы пытается подобрать для переменных из He такие значения, при которых вычисление хвоста R успешно завершится.

Точный смысл конструкции поиска проще всего можно определить через смысл более простых конструкций: присваивания и распутья. А именно, поиск

S" $iter S' :: He R эквивалентен тропе

S" :: He, \{ R; S' $iter S' :: He R; }

Эта тропа опять содержит конструкцию поиска, которую можно "развернуть" с помощью точно такого же преобразования. Получаем

S" :: He, \{ R;

S' :: He, \{ R;

S' $iter S' :: He R;

};}

повторив этот процесс бесконечное число раз, получаем, что исходная конструкция поиска эквивалентна бесконечной конструкции

S" :: He, \{ R;

S' :: He, \{ R;

S' :: He, \{ R;

...

... };};}

Рассмотрим пример использования конструкции поиска - определение функции факториал:

$func Fact sN = sFact;

Fact

{

0 = 1;

sN = <"*" sN <Fact <"-" sN 1>>>;

};

Недостаток этого рекурсивного определения в том, что происходит накопление вызовов функции "*", ожидающих пока рекурсия развернется до конца. Можно дать "более итеративное" определение функции Fact (при этом потребуется вспомогательная функция Fact-Aux).

$func Fact sN = sFact;

$func Fact-Aux sR sK = sFact;

Fact sN =

<Fact-Aux 1 sN>;

Fact-Aux sR sK =

{

sK : 0

= sR;

= <Fact-Aux <"*" sR sK> <"-" sK 1>>;

};

То же самое изображается с помощью конструкции поиска следующим образом.

$func Fact sN = sFact;

Fact sN =

1 sN

$iter <"*" sR sK> <"-" sK 1>

:: sR sK,

sK : 0,

= sR;