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;