Dari apa yang saya baca: Alasannya adalah karena tidak mudah untuk menentukan metode mana yang akan benar-benar disebut karena kita memiliki warisan.
Namun, mengapa Java setidaknya tidak memiliki optimisasi rekursi ekor untuk metode statis dan menerapkan cara yang tepat untuk memanggil metode statis dengan kompiler?
Mengapa Java tidak memiliki dukungan sama sekali untuk rekursi ekor?
Saya tidak yakin apakah ada kesulitan di sini sama sekali.
Mengenai duplikat yang disarankan , seperti yang dijelaskan oleh Jörg W Mittag 1 :
- Pertanyaan lain bertanya tentang TCO, yang ini tentang TRE. TRE jauh lebih sederhana daripada TCO.
- Selain itu, pertanyaan lain bertanya tentang batasan apa yang dikenakan JVM pada implementasi bahasa yang ingin dikompilasi ke JVM, pertanyaan ini menanyakan tentang Java, yang merupakan satu bahasa yang tidak dibatasi oleh JVM, karena spesifikasi JVM dapat diubah oleh orang yang sama yang mendesain Java.
- Dan terakhir, bahkan tidak ada batasan dalam JVM tentang TRE, karena JVM memang memiliki intra-metode GOTO, yang merupakan semua yang diperlukan untuk TRE
1 Pemformatan ditambahkan untuk memanggil poin yang dibuat.
Jawaban:
Seperti yang dijelaskan oleh Brian Goetz (Arsitek Bahasa Jawa di Oracle) dalam video ini :
Apa pun yang mengubah jumlah bingkai pada tumpukan akan merusak ini dan akan menyebabkan kesalahan. Dia mengakui ini adalah alasan yang bodoh, dan sejak itu para pengembang JDK telah mengganti mekanisme ini.
Lebih lanjut ia menyebutkan bahwa itu bukan prioritas, tetapi rekursi ekor itu
NB Ini berlaku untuk HotSpot dan OpenJDK, VM lain mungkin berbeda.
sumber
Java tidak memiliki optimasi panggilan ekor untuk alasan yang sama sebagian besar bahasa imperatif tidak memilikinya. Loop imperatif adalah gaya bahasa yang disukai, dan programmer dapat mengganti rekursi ekor dengan loop imperatif. Kompleksitas tidak sepadan untuk fitur yang penggunaannya tidak disarankan karena masalah gaya.
Hal ini di mana pemrogram ingin kadang-kadang menulis dalam gaya FP dalam bahasa yang tidak penting hanya menjadi populer dalam 10 tahun terakhir, setelah komputer mulai melakukan penskalaan dalam core bukan GHz. Bahkan sekarang, itu tidak sepopuler itu. Jika saya menyarankan mengganti loop imperatif dengan rekursi ekor di tempat kerja, setengah dari peninjau kode akan tertawa dan setengah lainnya akan memberikan tampilan bingung. Bahkan dalam pemrograman fungsional, Anda biasanya menghindari rekursi ekor kecuali konstruksi lain seperti fungsi tingkat tinggi tidak pas bersih.
sumber
for
loop" (dan juga untuk fungsi kelas vs objek). Saya tidak akan menyebutnya "imperatif fanatik" tetapi saya tidak berpikir itu akan menjadi permintaan yang sangat tinggi pada tahun 1995 ketika perhatian utama mungkin kecepatan Jawa, dan kurangnya obat generik.Java tidak memiliki optimasi panggilan tinggi karena JVM tidak memiliki bytecode untuk panggilan ekor (ke beberapa pointer fungsi yang tidak diketahui secara statis , misalnya metode dalam beberapa vtable).
Sepertinya karena alasan sosial (dan mungkin teknis), menambahkan operasi bytecode baru di JVM (yang akan membuatnya tidak kompatibel dengan versi sebelumnya dari JVM) sangat sulit bagi pemilik spesifikasi JVM.
Alasan teknis untuk tidak menambahkan bytecode baru dalam spesifikasi JVM termasuk fakta bahwa implementasi JVM kehidupan nyata adalah perangkat lunak yang sangat rumit (misalnya karena banyak optimasi JIT yang dilakukannya).
Tail Tail ke beberapa fungsi yang tidak diketahui membutuhkan penggantian frame stack saat ini dengan yang baru, dan operasi itu harusnya ada di JVM (ini bukan hanya masalah mengubah kompiler pembuat bytecode).
sumber
Kecuali jika suatu bahasa memiliki sintaks khusus untuk membuat panggilan ekor (rekursif atau sebaliknya) dan kompiler akan mengomel ketika panggilan ekor diminta tetapi tidak dapat dihasilkan, optimasi "opsional" panggilan ekor atau pengulangan ekor akan menghasilkan situasi di mana sebuah karya kode mungkin memerlukan kurang dari 100 byte tumpukan pada satu mesin, tetapi lebih dari 100.000.000 byte tumpukan pada yang lain. Perbedaan seperti itu harus dianggap kualitatif daripada sekadar kuantitatif.
Diharapkan mesin mungkin memiliki ukuran tumpukan yang berbeda, dan dengan demikian selalu memungkinkan kode untuk bekerja pada satu mesin tetapi meniup tumpukan pada yang lain. Namun, secara umum, kode yang akan bekerja pada satu mesin bahkan ketika stack secara artifisial cenderung akan bekerja pada semua mesin dengan ukuran stack "normal". Namun, jika metode yang berulang 1.000.000 dalam adalah tail-call dioptimalkan pada satu mesin tetapi tidak pada yang lain, eksekusi pada mesin sebelumnya kemungkinan akan bekerja bahkan jika tumpukannya sangat kecil, dan gagal pada yang terakhir meskipun tumpukannya sangat besar. .
sumber
Saya pikir rekursi panggilan ekor tidak digunakan di Jawa terutama karena hal itu akan mengubah jejak stack dan karenanya membuat debugging program menjadi lebih sulit. Saya pikir salah satu tujuan utama Java adalah untuk memungkinkan programmer untuk dengan mudah men-debug kode mereka, dan stack tracing sangat penting untuk melakukan itu terutama di lingkungan pemrograman yang sangat berorientasi objek. Karena iterasi dapat digunakan sebagai gantinya, panitia bahasa pasti mengira itu tidak layak menambahkan rekursi ekor.
sumber