Рекурсия без рекурсии
Как обойтись без рекурсии в случаях, когда кажется, что иначе нельзя?
Часто используете рекурсию в 1С? Как же без неё. Иногда приходится делать рекурсивные методы, даже если очень этого не хочется. Например:
Нужно найти отбор поля в настройках компоновки данных. И, естественно, нужна рекурсия, ведь отбор может содержать группы с вложенными отборами. Обычно, это делается примерно так:
Находим элемент отбора с переданным полем:
Но что делать, если нет возможности (или желания) делать рекурсивный код? Давайте попробуем обойтись без него (Никаких самовызовов):
Назовём этот подход “Рекурсия без рекурсии”. Практически, мы добиваемся того же результата. Но рекурсию не используем.
Как это работает:
- Объявляем массив, в котором будем содержать все коллекции, которые нужно перебрать
- Добавляем в массив переданную в наш метод изначальную коллекцию
- Пробегаем наш набор, а внутри сразу пробегаем все элементы.
- Если среди элементов мы так же находим коллекцию, то добавляем её в наш массив.
Таким образом, все найденные коллекции добавляются “в очередь” и перебираются позднее.
Зачем это нужно?
Бывают ситуации, когда нет возможности описать метод, но необходимо выполнить рекурсивный перебор. Например, в куске произвольного алгоритма.
Выполнить(ТекстАлгоритма);
Такое используется в шагах бизнес-процессов Документооборота. И в старой доброй Конвертации данных 2.0. В этом случае кусок кода будет выглядеть так:
Этот кусок алгоритма делает рекурсивный перебор, но при этом не создаёт самой рекурсии, а значит и не требует создания отдельного метода. Теперь его можно свободно поместить в текст для метода Выполнить().
Однако, описанный в статье подход работает немного иначе, чем стандартный с рекурсией. Дело в том, что “рекурсивный” перебирает подчиненные элементы сразу, а “нерекурсивный” - добавляет новые коллекции в очередь. И обработает тогда, когда до них эта очередь дойдёт. Результат такой же, но скорость выполнения может отличаться. А уже в чью сторону - зависит от конкретной ситуации.