Sì, alcune lingue e compilatori convertiranno la logica ricorsiva in logica non ricorsiva. Questo è noto come ottimizzazione delle chiamate di coda - notare che non tutte le chiamate ricorsive sono ottimizzabili per le chiamate di coda. In questa situazione, il compilatore riconosce una funzione del modulo:
int foo(n) {
...
return bar(n);
}
Qui, la lingua è in grado di riconoscere che il risultato che viene restituito è il risultato di un'altra funzione e cambiare una chiamata di funzione con un nuovo frame dello stack in un salto.
Realizza che il classico metodo fattoriale:
int factorial(n) {
if(n == 0) return 1;
if(n == 1) return 1;
return n * factorial(n - 1);
}
non è ottimizzabile per le chiamate di coda a causa dell'ispezione necessaria al ritorno.
Per rendere ottimizzabile questa chiamata in coda,
int _fact(int n, int acc) {
if(n == 1) return acc;
return _fact(n - 1, acc * n);
}
int factorial(int n) {
if(n == 0) return 1;
return _fact(n, 1);
}
Compilando questo codice con gcc -O2 -S fact.c
(il -O2 è necessario per abilitare l'ottimizzazione nel compilatore, ma con più ottimizzazioni del -O3 diventa difficile da leggere per un essere umano ...)
_fact:
.LFB0:
.cfi_startproc
cmpl $1, %edi
movl %esi, %eax
je .L2
.p2align 4,,10
.p2align 3
.L4:
imull %edi, %eax
subl $1, %edi
cmpl $1, %edi
jne .L4
.L2:
rep
ret
.cfi_endproc
Si può vedere nel segmento .L4
, jne
piuttosto che un call
(che fa una chiamata di subroutine con un nuovo frame dello stack).
Si noti che questo è stato fatto con C. L'ottimizzazione delle chiamate di coda in Java è difficile e dipende dall'implementazione di JVM: coda-ricorsione + java e coda-ricorsione + ottimizzazione sono buoni set di tag da sfogliare. Si possono trovare altre lingue JVM sono in grado di ottimizzare la ricorsione in coda migliore (prova clojure (che richiede il ripresentarsi alla chiamata di coda ottimizzare), o di scala).
return recursecall(args);
per la ricorsione, le cose più complesse sono possibili creando uno stack esplicito e liquidandolo, ma dubito che lo faranno