Votre description de votre algorithme est vraiment trop vague pour l'évaluer à ce stade. Mais, voici quelques éléments à considérer.
CPS
En fait, il existe un moyen de transformer n'importe quel code en un formulaire qui n'utilise que des appels de queue. Il s'agit de la transformation CPS. CPS ( Continuation-Passing Style ) est une forme d'expression de code en passant à chaque fonction une continuation. Une continuation est une notion abstraite représentant "le reste d'un calcul". Dans le code exprimé sous forme CPS, la façon naturelle de réifier une continuation est comme une fonction qui accepte une valeur. Dans CPS, au lieu d'une fonction renvoyant une valeur, il applique à la place la fonction représentant la continuation en cours au "retourné" par la fonction.
Par exemple, considérez la fonction suivante:
(lambda (a b c d)
(+ (- a b) (* c d)))
Cela pourrait être exprimé en CPS comme suit:
(lambda (k a b c d)
(- (lambda (v1)
(* (lambda (v2)
(+ k v1 v2))
a b))
c d))
C'est moche et souvent lent, mais cela présente certains avantages:
- La transformation peut être complètement automatisée. Il n'est donc pas nécessaire d'écrire (ou de voir) le code sous forme CPS.
- Combiné avec le thunking et le trampoline , il peut être utilisé pour fournir une optimisation des appels de queue dans des langues qui ne fournissent pas d'optimisation des appels de queue. (L'optimisation de l'appel de queue des fonctions directement récursives de la queue peut être réalisée par d'autres moyens, tels que la conversion de l'appel récursif en boucle. Mais la récursivité indirecte n'est pas aussi triviale à convertir de cette manière.)
- Avec CPS, les continuations deviennent des objets de première classe. Étant donné que les continuations sont l'essence du contrôle, cela permet à pratiquement n'importe quel opérateur de contrôle d'être implémenté comme une bibliothèque sans nécessiter de prise en charge particulière de la langue. Par exemple, goto, exceptions et threading coopératif peuvent tous être modélisés à l'aide de continuations.
TCO
Il me semble que la seule raison de se préoccuper de la récursivité de queue (ou des appels de queue en général) est à des fins d'optimisation de l'appel de queue (TCO). Donc, je pense qu'une meilleure question à poser est "ma transformation donne-t-elle un code qui soit optimisé par l'appel de queue?".
Si nous considérons une fois de plus CPS, l'une de ses caractéristiques est que le code exprimé en CPS consiste uniquement en appels de queue. Puisque tout est un appel de queue, nous n'avons pas besoin d'enregistrer un point de retour dans la pile. Donc, tout le code sous forme CPS doit être optimisé pour les appels de queue, non?
Enfin, pas tout à fait. Vous voyez, alors qu'il peut sembler que nous avons éliminé la pile, tout ce que nous avons fait est simplement de changer la façon dont nous la représentons. La pile fait maintenant partie de la fermeture représentant une continuation. Donc, CPS ne fait pas comme par magie tous nos appels de code optimisés.
Donc, si CPS ne peut pas tout faire TCO, y a-t-il une transformation spécifiquement pour la récursivité directe qui le peut? Non, pas en général. Certaines récursions sont linéaires, mais d'autres ne le sont pas. Les récursions non linéaires (par exemple, arborescentes) doivent simplement maintenir un état variable quelque part.