La tua descrizione del tuo algoritmo è davvero troppo vaga per valutarla a questo punto. Ma qui ci sono alcune cose da considerare.
CPS
In effetti, esiste un modo per trasformare qualsiasi codice in un modulo che utilizza solo le chiamate di coda. Questa è la trasformazione CPS. CPS ( Continuation-Passing Style ) è una forma di espressione del codice passando ogni funzione una continuazione. Una continuazione è una nozione astratta che rappresenta "il resto di una valutazione". Nel codice espresso in formato CPS, il modo naturale di reificare una continuazione è come una funzione che accetta un valore. In CPS, anziché una funzione che restituisce un valore, applica invece la funzione che rappresenta la continuazione corrente all'essere "restituito" dalla funzione.
Ad esempio, considerare la seguente funzione:
(lambda (a b c d)
(+ (- a b) (* c d)))
Questo potrebbe essere espresso in CPS come segue:
(lambda (k a b c d)
(- (lambda (v1)
(* (lambda (v2)
(+ k v1 v2))
a b))
c d))
È brutto e spesso lento, ma presenta alcuni vantaggi:
- La trasformazione può essere completamente automatizzata. Quindi non è necessario scrivere (o vedere) il codice in formato CPS.
- Combinato con thunking e trampolining , può essere utilizzato per fornire l'ottimizzazione della coda in lingue che non forniscono l'ottimizzazione della coda. (L'ottimizzazione della chiamata di coda delle funzioni direttamente ricorsive della coda può essere realizzata con altri mezzi, come convertire la chiamata ricorsiva in un ciclo. Ma la ricorsione indiretta non è così banale da convertire in questo modo.)
- Con CPS, le continuazioni diventano oggetti di prima classe. Poiché le continuazioni sono l'essenza del controllo, ciò consente praticamente a qualsiasi operatore di controllo di essere implementato come libreria senza richiedere alcun supporto speciale dal linguaggio. Ad esempio, goto, eccezioni e threading cooperativo possono essere tutti modellati utilizzando le continuazioni.
TCO
Mi sembra che l'unica ragione per occuparsi della ricorsione della coda (o delle chiamate in coda in generale) sia ai fini dell'ottimizzazione delle chiamate in coda (TCO). Quindi penso che una domanda migliore da porsi sia "il mio codice di rendimento di trasformazione è ottimizzabile per le chiamate in coda?".
Se consideriamo ancora una volta CPS, una delle sue caratteristiche è che il codice espresso in CPS è costituito esclusivamente da chiamate di coda. Poiché tutto è un richiamo, non è necessario salvare un punto di ritorno nello stack. Quindi tutto il codice in formato CPS deve essere ottimizzato per la coda, giusto?
Bene, non proprio. Vedi, mentre potrebbe sembrare che abbiamo eliminato lo stack, tutto ciò che abbiamo fatto è semplicemente cambiare il modo in cui lo rappresentiamo. Lo stack fa ora parte della chiusura che rappresenta una continuazione. Quindi CPS non rende magicamente ottimizzato tutto il nostro codice di coda.
Quindi, se CPS non può fare tutto il TCO, c'è una trasformazione specifica per la ricorsione diretta che può? No, non in generale. Alcune ricorsioni sono lineari, ma altre no. Le ricorsioni non lineari (ad es. Albero) devono semplicemente mantenere una quantità variabile di stato da qualche parte.