Перейти к основному содержимому
Версия: 4.x

Оператор 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 значений бесконечно). В этом случае необходимо также учитывать текущей порядок в этом списке, и также проталкивать его внутрь запроса. Эти ограничения будут устранены в будущих версиях, но в текущей версии их рекомендуется учитывать.