Oui, en fait, vous pouvez prendre un peu de code et de convertir chaque appel de fonction, et que chaque retour dans une queue d'appel. Ce que vous finissez avec est appelé continuation passing style, ou CPS.
Par exemple, voici une fonction contenant deux appels récursifs:
(define (count-tree t)
(if (pair? t)
(+ (count-tree (car t)) (count-tree (cdr t)))
1))
Et voici à quoi il devrait ressembler si vous avez converti cette fonction pour la continuation, passant du style:
(define (count-tree-cps t ctn)
(if (pair? t)
(count-tree-cps (car t)
(lambda (L) (count-tree-cps (cdr t)
(lambda (R) (ctn (+ L R))))))
(ctn 1)))
L'argument supplémentaire, ctn
, est une procédure qui count-tree-cps
de la queue-les appels au lieu de revenir. (sdcvvc la réponse dit que vous ne pouvez pas tout faire en O(1) de l'espace, et que c'est correct; ici, chaque suite est une fermeture qui prend de la mémoire.)
Je n'ai pas transformer les appels à l' car
ou cdr
ou +
en queue-les appels. Qui pourrait être aussi bien fait, mais je suppose que ceux de la feuille d'appels serait effectivement insérée.
Maintenant pour la partie la plus amusante. Poulet Régime ne fait cette conversion sur la totalité du code, il compile. Les procédures compilées par le Poulet ne jamais revenir. Il y a un article classique expliquant pourquoi le Poulet Régime de cela, écrit en 1994, avant de Poulet a été mis en œuvre: les INCONVÉNIENTS ne doivent pas contre ses arguments, Partie II: Cheney sur le M. T. A.
De manière assez surprenante, la continuation passing style est assez commun en JavaScript. Vous pouvez l'utiliser pour faire de longue calcul, en évitant le navigateur de script lent" popup. Et il est attractif pour des Api asynchrones. jQuery.get
(un simple wrapper autour de XMLHttpRequest) est clairement dans le prolongement de passage de style; le dernier argument est une fonction.