Seperti jawaban lain yang disebutkan, CLR memang mendukung pengoptimalan panggilan ekor dan tampaknya itu sedang dalam perbaikan progresif secara historis. Tetapi mendukungnya di C # memiliki Proposal
masalah terbuka di repositori git untuk desain bahasa pemrograman C # Mendukung rekursi ekor # 2544 .
Anda dapat menemukan beberapa detail dan info berguna di sana. Misalnya @jaykrell disebutkan
Biarkan saya memberikan apa yang saya tahu.
Terkadang tailcall adalah kinerja win-win. Itu bisa menghemat CPU. jmp lebih murah daripada call / ret. Ini bisa menghemat stack. Menyentuh lebih sedikit tumpukan menghasilkan lokalitas yang lebih baik.
Terkadang tailcall adalah kerugian kinerja, tumpukan menang. CLR memiliki mekanisme yang kompleks untuk meneruskan lebih banyak parameter ke callee daripada yang diterima pemanggil. Maksud saya secara khusus lebih banyak ruang tumpukan untuk parameter. Ini lambat. Tapi itu menghemat tumpukan. Ini hanya akan dilakukan dengan ekor. awalan.
Jika parameter pemanggil lebih besar tumpukan dari parameter callee, biasanya ini merupakan transformasi win-win yang cukup mudah. Mungkin ada faktor-faktor seperti perubahan posisi parameter dari yang dikelola menjadi integer / float, dan menghasilkan StackMaps yang tepat dan semacamnya.
Sekarang, ada sudut lain, yaitu algoritma yang menuntut penghapusan tailcall, untuk tujuan dapat memproses data besar secara sewenang-wenang dengan tumpukan tetap / kecil. Ini bukan tentang kinerja, tetapi tentang kemampuan untuk berlari sama sekali.
Juga izinkan saya menyebutkan (sebagai info tambahan), Ketika kami membuat lambda yang dikompilasi menggunakan kelas ekspresi di System.Linq.Expressions
namespace, ada argumen bernama 'tailCall' yang seperti yang dijelaskan dalam komentarnya.
Bool yang menunjukkan apakah pengoptimalan panggilan ekor akan diterapkan saat menyusun ekspresi yang dibuat.
Saya belum mencobanya, dan saya tidak yakin bagaimana ini dapat membantu terkait dengan pertanyaan Anda, tetapi Mungkin seseorang dapat mencobanya dan mungkin berguna dalam beberapa skenario:
var myFuncExpression = System.Linq.Expressions.Expression.Lambda<Func< … >>(body: … , tailCall: true, parameters: … );
var myFunc = myFuncExpression.Compile();
preemptive
(misalnya algoritma faktorial) danNon-preemptive
(misalnya fungsi ackermann). Penulis hanya memberikan dua contoh yang telah saya sebutkan tanpa memberikan alasan yang tepat di balik percabangan ini. Apakah percabangan ini sama dengan fungsi rekursif ekor dan non-ekor?