Sua descrição do seu algoritmo é realmente muito vaga para avaliá-lo neste momento. Mas, aqui estão algumas coisas a considerar.
CPS
De fato, existe uma maneira de transformar qualquer código em um formulário que use apenas chamadas de cauda. Essa é a transformação do CPS. O CPS ( estilo de passagem de continuação ) é uma forma de expressar código, passando para cada função uma continuação. Uma continuação é uma noção abstrata que representa "o restante de uma comparação". No código expresso no formato CPS, a maneira natural de reificar uma continuação é como uma função que aceita um valor. No CPS, em vez de uma função retornar um valor, ela aplica a função que representa a continuação atual ao ser "retornado" pela função.
Por exemplo, considere a seguinte função:
(lambda (a b c d)
(+ (- a b) (* c d)))
Isso pode ser expresso no CPS da seguinte maneira:
(lambda (k a b c d)
(- (lambda (v1)
(* (lambda (v2)
(+ k v1 v2))
a b))
c d))
É feio e geralmente lento, mas tem certas vantagens:
- A transformação pode ser completamente automatizada. Portanto, não há necessidade de escrever (ou ver) o código no formato CPS.
- Combinado com batidas e trampolins , ele pode ser usado para fornecer otimização de chamada de cauda em idiomas que não fornecem otimização de chamada de cauda. (A otimização de chamada de cauda de funções diretamente recursivas de cauda pode ser realizada por outros meios, como converter a chamada recursiva em um loop. Mas a recursão indireta não é tão trivial para converter dessa maneira.)
- Com o CPS, as continuações se tornam objetos de primeira classe. Como as continuações são a essência do controle, isso permite que praticamente qualquer operador de controle seja implementado como uma biblioteca sem exigir nenhum suporte especial do idioma. Por exemplo, saltar, exceções e encadeamento cooperativo podem ser modelados usando continuações.
TCO
Parece-me que a única razão para se preocupar com recursão de cauda (ou chamadas de cauda em geral) é para fins de otimização de chamada de cauda (TCO). Então, acho que uma pergunta melhor a ser feita é "minha transformação gera código que é otimizável por chamada de cauda?".
Se considerarmos novamente o CPS, uma de suas características é que o código expresso no CPS consiste apenas em chamadas de cauda. Como tudo é uma chamada final, não precisamos salvar um ponto de retorno na pilha. Portanto, todo o código no formato CPS deve ser otimizado para chamada final, certo?
Bem, não exatamente. Você vê, embora possa parecer que eliminamos a pilha, tudo o que fizemos foi apenas mudar a maneira como a representamos. A pilha agora faz parte do fechamento, representando uma continuação. Portanto, o CPS não magicamente otimiza todo o nosso código de chamada final.
Portanto, se o CPS não pode fazer tudo TCO, existe uma transformação específica para recursão direta que pode? Não, não em geral. Algumas recursões são lineares, mas outras não. Recursões não lineares (por exemplo, árvore) devem simplesmente manter uma quantidade variável de estado em algum lugar.