Ваше описание вашего алгоритма действительно слишком расплывчато, чтобы оценить его на данный момент. Но вот некоторые вещи для рассмотрения.
КПС
Фактически, есть способ преобразовать любой код в форму, которая использует только хвостовые вызовы. Это преобразование CPS. CPS ( Continuation-Passing Style ) - это форма выражения кода, передавая каждой функции продолжение. Продолжением является абстрактное понятие, представляющее «остальную часть вычисления». В коде , выраженной в виде CPS, естественный способ материализовать продолжение является как функция , которая принимает значение. В CPS вместо функции, возвращающей значение, она применяет функцию, представляющую текущее продолжение, к функции, «возвращаемой» функцией.
Например, рассмотрим следующую функцию:
(lambda (a b c d)
(+ (- a b) (* c d)))
Это может быть выражено в CPS следующим образом:
(lambda (k a b c d)
(- (lambda (v1)
(* (lambda (v2)
(+ k v1 v2))
a b))
c d))
Это уродливо и часто медленно, но у него есть определенные преимущества:
- Преобразование может быть полностью автоматизировано. Поэтому нет необходимости писать (или видеть) код в форме CPS.
- В сочетании с thunking и trampolining он может использоваться для обеспечения оптимизации хвостового вызова на языках, которые не обеспечивают оптимизацию хвостового вызова. (Оптимизация хвостового вызова непосредственно хвостовой рекурсивной функции может быть выполнена с помощью других средств, таких как преобразование рекурсивного вызова в цикл. Но косвенная рекурсия не так тривиальна для преобразования таким способом.)
- С CPS продолжения становятся первоклассными объектами. Поскольку продолжения являются сущностью управления, это позволяет реализовать практически любой оператор управления в виде библиотеки, не требуя специальной поддержки языка. Например, goto, исключения и совместная обработка потоков могут быть смоделированы с использованием продолжений.
TCO
Мне кажется, что единственная причина, связанная с хвостовой рекурсией (или хвостовыми вызовами в целом), заключается в целях оптимизации хвостовых вызовов (TCO). Поэтому я думаю, что лучше задать вопрос: «Может ли мой код преобразования преобразовать с помощью хвостового вызова?».
Если мы еще раз рассмотрим CPS, одной из его характеристик является то, что код, выраженный в CPS, состоит исключительно из хвостовых вызовов. Поскольку все является хвостовым вызовом, нам не нужно сохранять точку возврата в стек. Таким образом, весь код в форме CPS должен быть оптимизирован с помощью хвостового вызова, верно?
Ну, не совсем. Видите ли, хотя может показаться, что мы удалили стек, все, что мы сделали, это просто изменили способ его представления. Стек теперь является частью замыкания, представляющего продолжение. Таким образом, CPS волшебным образом не делает весь наш код оптимизированным.
Так что, если CPS не может сделать все TCO, существует ли преобразование специально для прямой рекурсии, которое может? Нет не вообще. Некоторые рекурсии линейны, а некоторые нет. Нелинейные (например, древовидные) рекурсии просто должны где-то поддерживать переменное количество состояний.