Clojure tidak melakukan optimasi panggilan ekor sendiri: ketika Anda memiliki fungsi rekursif ekor dan Anda ingin mengoptimalkannya, Anda harus menggunakan formulir khusus recur
. Demikian pula, jika Anda memiliki dua fungsi yang saling rekursif, Anda dapat mengoptimalkannya hanya dengan menggunakan trampoline
.
Scala compiler dapat melakukan TCO untuk fungsi rekursif, tetapi tidak untuk dua fungsi rekursif yang saling menguntungkan.
Setiap kali saya membaca tentang keterbatasan ini, mereka selalu dianggap berasal dari batasan intrinsik dengan model JVM. Saya tidak tahu banyak tentang kompiler, tapi ini sedikit membingungkan saya. Biarkan saya ambil contohnya Programming Scala
. Di sini fungsinya
def approximate(guess: Double): Double =
if (isGoodEnough(guess)) guess
else approximate(improve(guess))
diterjemahkan ke dalam
0: aload_0
1: astore_3
2: aload_0
3: dload_1
4: invokevirtual #24; //Method isGoodEnough:(D)Z
7: ifeq
10: dload_1
11: dreturn
12: aload_0
13: dload_1
14: invokevirtual #27; //Method improve:(D)D
17: dstore_1
18: goto 2
Jadi, pada level bytecode, kita hanya perlu goto
. Dalam hal ini, sebenarnya, kerja keras dilakukan oleh kompiler.
Fasilitas apa dari mesin virtual yang mendasarinya yang memungkinkan kompiler menangani TCO dengan lebih mudah?
Sebagai catatan, saya tidak berharap mesin yang sebenarnya jauh lebih pintar daripada JVM. Namun, banyak bahasa yang mengkompilasi ke kode asli, seperti Haskell, tampaknya tidak memiliki masalah dengan mengoptimalkan panggilan ekor (well, Haskell kadang-kadang bisa karena kemalasan, tapi itu masalah lain).