Sim, alguns idiomas e complementadores converterão a lógica recursiva em lógica não recursiva. Isso é conhecido como otimização de chamada final - observe que nem todas as chamadas recursivas são otimizadas para chamada final. Nessa situação, o compilador reconhece uma função do formulário:
int foo(n) {
...
return bar(n);
}
Aqui, o idioma é capaz de reconhecer que o resultado retornado é o resultado de outra função e alterar uma chamada de função com um novo quadro de pilha em um salto.
Perceba que o método fatorial clássico:
int factorial(n) {
if(n == 0) return 1;
if(n == 1) return 1;
return n * factorial(n - 1);
}
não é otimizado para chamada final devido à inspeção necessária no retorno.
Para tornar essa chamada final otimizável,
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 esse código com gcc -O2 -S fact.c
(o -O2 é necessário para ativar a otimização no compilador, mas com mais otimizações de -O3 fica difícil para um ser humano ler ...)
_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
Pode-se ver no segmento .L4
, em jne
vez de um call
(que faz uma chamada de sub-rotina com um novo quadro de pilha).
Observe que isso foi feito com C. A otimização de chamada de cauda em java é difícil e depende da implementação da JVM - tail-recursion + java e tail-recursion + optimization são bons conjuntos de tags para navegar. Você pode achar que outros idiomas da JVM são capazes de otimizar melhor a recursão da cauda (tente o clojure (que requer que a repetição para otimizar a chamada da cauda) ou scala).
return recursecall(args);
para a recursividade, o material mais complexo é possível através da criação de uma pilha explícita e enrolando-a para baixo, mas eu duvido que eles vão