হ্যাঁ, কিছু ভাষা এবং সংকলক পুনরাবৃত্ত লজিকে নন-রিকার্সিভ লজিকে রূপান্তর করবে। এটি লেজ কল অপ্টিমাইজেশন হিসাবে পরিচিত - নোট করুন যে সমস্ত পুনরাবৃত্তি কলগুলি কল কলটি অপটিমাইজযোগ্য নয়। এই পরিস্থিতিতে, সংকলক ফর্মটির একটি ক্রিয়াকলাপ স্বীকৃত:
int foo(n) {
...
return bar(n);
}
এখানে ভাষাটি চিনতে সক্ষম হয়েছে যে ফলাফলটি ফেরত দেওয়া হচ্ছে অন্য ফাংশন থেকে প্রাপ্ত ফলাফল এবং একটি নতুন স্ট্যাক ফ্রেমের সাহায্যে একটি ফাংশন কলকে একটি জাম্পে পরিবর্তন করতে হবে।
অনুধাবন করুন যে ক্লাসিক কল্পিত পদ্ধতি:
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
সংকলন করে (-O2 সংকলকটিতে অপ্টিমাইজেশন সক্ষম করতে প্রয়োজনীয়, তবে -O3 এর আরও অনুকূলিতকরণের সাথে এটি মানুষের পক্ষে পড়া শক্ত হয়ে যায় ...)
_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);
আপনার পুনরাবৃত্তির জন্য কাজ করে তবেই আরও কার্যকর জিনিসগুলি স্পষ্টভাবে স্ট্যাক তৈরি করে এবং এটি ঘুরিয়ে দিয়ে সম্ভব হয় তবে আমি সন্দেহ করি তারা করবে