কেভিন খুব সংক্ষেপে এই নির্দিষ্ট কোড স্নিপেটটি কীভাবে কাজ করে তা নির্দেশ করে (কেন এটি যথেষ্ট বোধগম্য) পাশাপাশি আমি সাধারণ কাজে ট্রাম্পোলাইনগুলি সম্পর্কে কিছু তথ্য যুক্ত করতে চেয়েছিলাম ।
টেল-কল অপ্টিমাইজেশন (টিসিও) ছাড়াই প্রতিটি ফাংশন কল বর্তমান এক্সিকিউশন স্ট্যাকটিতে একটি স্ট্যাক ফ্রেম যুক্ত করে। ধরুন সংখ্যার একটি কাউন্টডাউন প্রিন্ট করার জন্য আমাদের একটি ফাংশন রয়েছে:
function countdown(n) {
if (n === 0) {
console.log("Blastoff!");
} else {
console.log("Launch in " + n);
countdown(n - 1);
}
}
আমরা যদি কল করি countdown(3)
, টিসিও ছাড়াই কল স্ট্যাকটি কেমন দেখায় তা বিশ্লেষণ করা যাক।
> countdown(3);
// stack: countdown(3)
Launch in 3
// stack: countdown(3), countdown(2)
Launch in 2
// stack: countdown(3), countdown(2), countdown(1)
Launch in 1
// stack: countdown(3), countdown(2), countdown(1), countdown(0)
Blastoff!
// returns, stack: countdown(3), countdown(2), countdown(1)
// returns, stack: countdown(3), countdown(2)
// returns, stack: countdown(3)
// returns, stack is empty
TCO সঙ্গে, প্রতিটি recursive কলে countdown
হয় লেজ অবস্থান তাই কোনও সময় স্ট্যাক ফ্রেম বরাদ্দ করা হয় (কিছুই কলের ফলাফলের আসতে ছাড়া অন্য কিছু করার বাকি আছে)। টিসিও ছাড়া স্ট্যাকটি আরও কিছুটা বড় হয়ে যায় n
।
ট্রাম্পোলাইনিং countdown
ফাংশনটির চারপাশে একটি মোড়ক .ুকিয়ে এই বিধিনিষেধের কাছাকাছি চলে । তারপরে, countdown
পুনরাবৃত্ত কলগুলি সম্পাদন করে না এবং পরিবর্তে কল করার জন্য তত্ক্ষণাত কোনও ফাংশন ফিরিয়ে দেয়। এখানে একটি বাস্তবায়ন উদাহরণ:
function trampoline(firstHop) {
nextHop = firstHop();
while (nextHop) {
nextHop = nextHop()
}
}
function countdown(n) {
trampoline(() => countdownHop(n));
}
function countdownHop(n) {
if (n === 0) {
console.log("Blastoff!");
} else {
console.log("Launch in " + n);
return () => countdownHop(n-1);
}
}
এটি কীভাবে কাজ করে তার আরও ভাল ধারণা পেতে, কল স্ট্যাকটি দেখুন:
> countdown(3);
// stack: countdown(3)
// stack: countdown(3), trampoline
// stack: countdown(3), trampoline, countdownHop(3)
Launch in 3
// return next hop from countdownHop(3)
// stack: countdown(3), trampoline
// trampoline sees hop returned another hop function, calls it
// stack: countdown(3), trampoline, countdownHop(2)
Launch in 2
// stack: countdown(3), trampoline
// stack: countdown(3), trampoline, countdownHop(1)
Launch in 1
// stack: countdown(3), trampoline
// stack: countdown(3), trampoline, countdownHop(0)
Blastoff!
// stack: countdown(3), trampoline
// stack: countdown(3)
// stack is empty
প্রতিটি পদক্ষেপে countdownHop
ফাংশনটি পরবর্তী ঘটনার প্রত্যক্ষ নিয়ন্ত্রণ ত্যাগ করে পরিবর্তে কল করে ফাংশনটি ফিরিয়ে দেয় যা এর পরে কী হতে চায় তা বর্ণনা করে । ট্রামপোলিন ফাংশন এটি পরে এটি কল করে এবং তারপরে যে কোনও ফাংশন ফিরে আসে এবং অন্য কোনও "পরবর্তী পদক্ষেপ" না পাওয়া পর্যন্ত কল করে calls একে ট্রামোলিনিং বলা হয় কারণ ক্রিয়াকলাপটি পুনরাবৃত্ত হওয়ার পরিবর্তে প্রতিটি পুনরাবৃত্ত কল এবং ট্রামপোলিন বাস্তবায়নের মধ্যে নিয়ন্ত্রণের প্রবাহ "বাউন্স" করে। যারা নিয়ন্ত্রণ পরিত্যাগ করে তোলে recursive কল, trampoline ফাংশন নিশ্চিত করতে পারে স্ট্যাক অত্যন্ত বড় পাবেন না। পার্শ্ব নোট: trampoline
সরলতার জন্য প্রত্যাবর্তন মানগুলি বাদ দেয়।
এটি একটি ভাল ধারণা কিনা তা জানা মুশকিল হতে পারে। প্রতিটি পদক্ষেপে একটি নতুন বন্ধের বরাদ্দ দেওয়ার কারণে কার্যকারিতা ক্ষতিগ্রস্থ হতে পারে। চতুর অপ্টিমাইজেশন এটিকে কার্যকর করতে পারে তবে আপনি কখনই জানেন না। ট্রাম্পোলাইনিং বেশিরভাগ হার্ড পুনরাবৃত্তির সীমাটি পাওয়ার জন্য দরকারী, উদাহরণস্বরূপ যখন কোনও ভাষা প্রয়োগ যখন সর্বাধিক কল স্ট্যাকের আকার নির্ধারণ করে।
loopy
উপচে পড়ে না কারণ এটি নিজেকে কল করে না ।