हां, कुछ भाषाएँ और शिकायतकर्ता पुनरावर्ती तर्क को गैर-पुनरावर्ती तर्क में बदल देंगे। इसे टेल कॉल ऑप्टिमाइजेशन के रूप में जाना जाता है - ध्यान दें कि सभी पुनरावर्ती कॉल टेल कॉल ऑप्टिमाइज़ नहीं होते हैं। इस स्थिति में, संकलक प्रपत्र के एक फ़ंक्शन को पहचानता है:
int foo(n) {
...
return bar(n);
}
यहां, भाषा यह पहचानने में सक्षम है कि जो परिणाम लौटाया जा रहा है, वह दूसरे फ़ंक्शन का परिणाम है और एक जंप में नए स्टैक फ्रेम के साथ फ़ंक्शन कॉल को बदलें।
एहसास है कि क्लासिक factorial विधि:
int factorial(n) {
if(n == 0) return 1;
if(n == 1) return 1;
return n * factorial(n - 1);
}
है न निरीक्षण वापसी पर आवश्यक की वजह से पूंछ कॉल optimizatable।
इस टेल कॉल को अनुकूलन योग्य बनाने के लिए,
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);
}
इस कोड को gcc -O2 -S fact.c
(-ओ 2 को कंपाइलर में ऑप्टिमाइज़ेशन को सक्षम करने के लिए आवश्यक है, लेकिन -ओ 3 के अधिक अनुकूलन के साथ इसे पढ़ना मानव के लिए कठिन हो जाता है ...)
_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
एक सेगमेंट में देख सकता है .L4
, jne
बजाय एक call
(जो एक नए स्टैक फ्रेम के साथ सबरूटीन कॉल करता है)।
कृपया ध्यान दें कि यह सी। टेल कॉल ऑप्टिमाइज़ेशन के साथ जावा में कठिन है और जेवीएम कार्यान्वयन पर निर्भर करता है - टेल-रिकर्सन + जावा और टेल-रिकर्सियन + ऑप्टिमाइज़ेशन ब्राउज़ करने के लिए अच्छे टैग सेट हैं। आप पा सकते हैं कि अन्य जेवीएम भाषाएं पूंछ की पुनरावृत्ति को बेहतर ढंग से अनुकूलित करने में सक्षम हैं (क्लोजर (जिसे टेल कॉल ऑप्टिमाइज़ करने के लिए पुनरावृत्ति की आवश्यकता है ), या स्केला की कोशिश करें)।
return recursecall(args);
पुनरावृत्ति के लिए है, एक स्पष्ट स्टैक बनाने और इसे नीचे घुमावदार करने से अधिक जटिल सामान संभव है, लेकिन मुझे संदेह है कि