Ya, beberapa bahasa dan pelengkap akan mengubah logika rekursif ke logika non-rekursif. Ini dikenal sebagai pengoptimalan panggilan ekor - perhatikan bahwa tidak semua panggilan rekursif dapat dioptimalkan panggilan ekor. Dalam situasi ini, kompiler mengenali fungsi dari form:
int foo(n) {
...
return bar(n);
}
Di sini, bahasa dapat mengenali bahwa hasil yang dikembalikan adalah hasil dari fungsi lain dan mengubah panggilan fungsi dengan bingkai tumpukan baru menjadi lompatan.
Sadarilah bahwa metode faktorial klasik:
int factorial(n) {
if(n == 0) return 1;
if(n == 1) return 1;
return n * factorial(n - 1);
}
adalah tidak ekor panggilan optimizatable karena pemeriksaan yang diperlukan pada kembali.
Untuk membuat panggilan ekor ini dapat dioptimalkan,
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);
}
Kompilasi kode ini dengan gcc -O2 -S fact.c
(-O2 diperlukan untuk mengaktifkan optimisasi dalam kompiler, tetapi dengan lebih banyak optimasi dari -O3 semakin sulit bagi manusia untuk membaca ...)
_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
Satu dapat melihat di segmen .L4
, jne
daripada call
(yang melakukan panggilan subrutin dengan bingkai tumpukan baru).
Harap perhatikan bahwa ini dilakukan dengan C. Optimasi panggilan ekor di java sulit dan tergantung pada implementasi JVM - pengulangan ekor + java dan pengoptimalan pengulangan ekor + pengoptimalan adalah set tag yang baik untuk dijelajahi. Anda mungkin menemukan bahasa JVM lainnya dapat mengoptimalkan rekursi ekor lebih baik (coba clojure (yang membutuhkan pengulangan untuk mengoptimalkan panggilan bolak-balik ), atau scala).
return recursecall(args);
rekursi, hal-hal yang lebih kompleks dimungkinkan dengan membuat tumpukan eksplisit dan memutarnya, tetapi saya ragu mereka akan