Оператор RECURSION
Оператор RECURSION
- создание свойства, реализующего рекурсию.
Синтаксис
RECURSION initialExpr STEP stepExpr [CYCLES YES | CYCLES NO | CYCLES IMPOSSIBLE]
Описание
Оператор RECURSION
создает свойство, реализующее рекурсию. Выражения, которое описывает очередной шаг рекурсии, может содержать, кроме обычного обращения к параметрам свойства, обращение к значению параметра на предыдущем шаге. Это обращение имеет синтаксис $name
, где name
- имя параметра.
Параметры
-
initialExpr
Выражение, значение которого является начальным свойством.
-
stepExpr
Выражение, значение которого является свойством шага рекурсии. Допускает специальный синтаксис
$name
для обращения к значению параметраname
на предыдущем шаге. -
CYCLES YES
Обозначает, что циклы допускаются.
-
CYCLES NO
Обозначает, что циклы не допускаются. Эта опция используется по умолчанию.
-
CYCLES IMPOSSIBLE
Обозначает, что циклы невозможны.
Примеры
CLASS Node;
edge = DATA BOOLEAN (Node, Node);
// итерация по integer от from к to (это свойство по умолчанию входит в модуль System)
iterate(i, from, to) = RECURSION i==from AND from IS INTEGER AND to IS INTEGER STEP i==$i+1 AND i<=to CYCLES IMPOSSIBLE;
// считает количество различных путей от a до b в графе
pathes 'Кол-во путей' (a, b) = RECURSION 1 AND a IS Node AND b==a STEP 1 IF edge(b, $b);
// определяет на каком уровне находится child от parent, и null если не является потомком (тем самым это свойство можно использовать для определения всех child'ов)
parent = DATA Group (Group);
level 'Уровень' (Group child, Group parent) = RECURSION 1 IF child IS Group AND parent == child
STEP 1 IF parent == parent($parent);
// числа Фибоначчи, свойство высчитывает все числа Фибоначи до значения to, (после будет возвращать null)
fib(i, to) = RECURSION 1 IF (i==0 OR i==1) AND to IS INTEGER STEP 1 IF (i==$i+1 OR i==$i+2) AND i<to CYCLES IMPOSSIBLE;
Заметим, что числа Фибоначчи можно реализовать без добавления параметра to:
fib(i) = RECURSION 1 IF (i==0 OR i==1) STEP 1 IF (i==$i+1 OR i==$i+2);
Но в текущей реализации оптимизатор платформы в меньшей степени ориентирован на работу с числами, поэтому пока не может определить, что функция шага возрастающая, и сам остановить рекурсию, искусственно создав соответствующие условие, как это сделано в верхнем примере. Еще больше вопросов возникает, когда это свойство необходимо отображать в динамическом списке (а в статическом списке это невозможно сделать, так как количество не NULL
значений бесконечно). В этом случае необходимо также учитывать текущей порядок в этом списке, и также проталкивать его внутрь запроса. Эти ограничения будут устранены в будущих версиях, но в текущей версии их рекомендуется учитывать.