موضوع مقاله: سبک ادامه دهی با انتقال پارامتر | مخاطب: عمومی | لحن: دانشنامه‌ای | ساختار: عنوان، مقدمه، 3 بخش، جمع‌بندی | مقاله: | # سبک ادامه دهی با انتقال پارامتر | مقدمه: در برنامه‌نویسی تابعی، روشِ "ادامه‌دهی با انتقال پارمتر" یا CPS، یک روش برنامه‌نویسی است که در آن flow|کنترل به شکل مستقیم و به فرم یک تداوم منتقل می‌شود (یک تداوم، نمایشی خلاصه از وضعیت کنترل یک برنامه کامپیوتری است و در یک زمان خاص از فرایند اجرا، جریان کامپیوتری را نشان می‌دهد). | ## بخش 1: سبک ادامه دهی با انتقال پارامتر | "جرالد جی ساسمن" و "گای ال استیل جونیور"، در گزارش‌ها "اِی.آی مِمو ۳۴۹" در سال ۱۹۷۵ این عبارت را ابداع کردند که باعث به کار افتادن اولین ورژن زبان برنامه‌نویسی "اسکیم" شد. مثال‌ها تابعی که به روش " ادامه‌دهی با انتقال پارمتر " نوشته شده باشد یک آرگومانِ اضافه دریافت خواهد کرد: یک تداوم صریح؛ یعنی یک تابع با یک آرگومان. وقتی تابع نوشته شده با روش " ادامه‌دهی با انتقال پارمتر " مقدار نهایی خود را حساب کند، با صدا زدن تابع تداوم و دادن مقدار نهایی به آن به عنوان آرگومان، آن را برمی‌گرداند. این بدان معناست که هنگام فراخوانی یک تابع CPS، تابع صدا زده شده وظیفه دارد که عملکرد و رویه‌ای فراهم کند تا همراه با مقدار بازگشتی زیر-روال فراخوانی شود.( زیر-روال مجموعه‌ای از دستورالعمل‌ها با نام یا آدرس خاصی هستند که هنگام احضار توسط برنامه اصلی اجرا می‌شوند). بیان کردن کد به این شکل، چیزهایی را صریح و مستقیم می‌کند که در روش برنامه‌نویسی مستقیم، به صورت ضمنی هستند. این‌ها عبارتند از : بازگشت‌های رویه‌ها، که به عنوان فراخوانی تداوم‌ها آشکار می‌شود؛ مقادیر میانی، که همگی اسم‌های داده شده هستند؛ ترتیب ارزیابی آرگومان‌ها، که صریح و مستقیم شده‌اند؛ و فراخوانی انتهایی که به سادگی یک رویه را با همان تداومِ تغییر نیافته که به صداکننده انتقال داده شده بود، فراخوانی می‌کند. کامپایلرهای تابعی و منطقی معمولاً از CPS به عنوان یک نمایش میانی استفاده می‌کنند در جایی که یک کامپایلر برای یک زبان برنامه‌نویسی امری یا رویه‌ای از فرم تخصیص تک‌ایستا (SSA) استفاده می‌کند.* SSA به شکل رسمی معادل با زیرمجموعه‌ای از CPS است ( به استثنای جریان کنترل غیرمحلی، که زمانی که CPS به عنوان نمایش میانی استفاده می‌شود، اتفاق نمی‌افتد).* کامپایلرهای تابعی همچنین می‌توانند به جای استفاده از thunk در CPS، که زیربرنامه‌ای است برای تزریق محاسبات به زیربرنامه دیگر، از فرم آنرمال (ANF) استفاده کنند (اما فقط برای زبان‌هایی که نیاز به تکنیک ارزیابی مشتاقانه دارند (تکنیک مشتاقانه یک روش است که در آن یک عبارت، به محض اینکه به یک متغیر محدود شود یا به عنوان یک آرگومان انتقال داده شود، ارزیابی می‌شود. CPS بیشتر توسط کامپایلرها استفاده می‌شود تا به عنوان یک سبک کلی یا محلی توسط برنامه‌نویس‌ها. در CPS هر تابع، یک آرگومان اضافه می‌گیرد که نمایان‌کننده این است که باید روی نتیجه‌ای که تابع محاسبه می‌کند، چه عملی انجام شود. این موضوع، همراه با یک سبک محدود‌کننده که انواع مدل‌هایی که معمولاً در دسترس هستند را ممنوع می‌کند، استفاده می‌شود تا معانی برنامه‌ها را نماش دهد و درنتیجه، تحلیل آن‌ها را ساده‌تر کند. این روش همچنین، بیان ساختارهای کنترل غیرمعمولی مثل پرتاب کردن/گرفتن یا سایر انتقال‌های غیرمحلی را آسان می‌کند. | ## بخش 2: سبک ادامه دهی با انتقال پارامتر | راز CPS این است که به یاد داشته باشیم : یک) هر تابعی یک آرگومان اضافی با عنوان "تداوم" تابع می‌گیرد و دو) هر آرگومانی در یک فراخوانی تابع باید یا یک متغیر باشد یا عبارت لامبدا (نه یک عبارت پیچیده‌تر). تاثیر این کار این است که عبارت انگاری پشت‌ورو می‌شود؛ زیرا قسمت‌های داخلی عبارات باید زودتر ارزیابی شوند، که در نتیجه CPS ترتیب ارزیابی را نیز همانند جریان کنترل صریح و مستقیم می‌کند. در مثال‌های بالا ما از ساده‌ترین قرارداد استفاده کردیم، با این حال گاهی اوقات مقادیر اولیه بولین ارائه می‌شوند که دو thunk می‌گیرند تا در دو حالت متفاوت فراخوانی بشوند، پس به جای فراخوانیِ (=& n 0 (lambda (b) (if b ... به همین شکل، گاهی اوقات بخش "if" خودش در CPS موجود نیست بلکه یک تابع به شکل زیر تعریف خواهد شد: if& که سه آرگومان دریافت خواهد کرد: یک شرط با مقدار درست یا غلط، و دو thunk متناظر با دو بازوی شرط. فاکتوریلِ روش مستقیم، همان‌طور که انتظار می‌رود، یک آرگومان دریافت خواهد کرد؛ اما فاکتوریل CPS که یک & در آخر اسم خود دارد دو آرگومان می‌گیرد: خود آرگومان معمول و یک تداوم. هر تابعی که یک تابع CPS شده را فراخوانی می‌کند باید یا تداوم جدیدی ارائه کند یا تداوم خودش را منتقل کند؛ هر فراخوانی از یک تابع CPS شده به یک تابع غیرCPS از یک تداوم ضمنی استفاده خواهد کرد. درنتیجه، برای مطمئن شدن از نبود یک استک مربوط به توابع، کل برنامه باید به CPS نوشته شده باشد. سی.پی.اس در هَسکِل در این بخش ما یک تابع به اسم pyth می‌نویسیم که با استفاده از قضیه فیثاغورث، هیپوتنوز را محاسبه می‌کند. به عنوان مثال در برنامه‌نویسی رابط کاربری (UI)، یک روال می‌تواند کادرهای محاوره‌ای تنظیم کند و آن‌ها را به همراه یک تابع تداوم، به چارچوب UI ارسال کند. وقتی کاربر دکمه "OK" را فشار دهد، فریمورک تابع تداوم را با فیلدهای به‌روزشده صدا می‌زند. فریمورک، می‌تواند تابع صدازده‌شده را در یک رشته کارگر اجرا کند، سپس تابع تداوم را در رشته اولیه با نتیجه رشته کارگر فراخوانی کند. | ## بخش 3: سبک ادامه دهی با انتقال پارامتر | استفاده از CPS بدون بهینه‌سازی فراخوانی نهایی (TCO)، نه تنها باعث می‌شود که تداوم ساخته‌شده به‌طور بالقوه در طول بازگشت رشد کند، بلکه حتی برای فراخوان پشته (کال استک) نیز همین اتفاق می‌افتد. استفاده و پیاده‌سازی از روش "ادامه‌دهی با انتقال پارمتر" می‌توان برای پیاده‌سازی تداوم‌ها و کنترل عملگر‌های جریان در یک زبان تابعی که دارای تداوم‌های کلاس-اول نیست اما دارای توابع کلاس-اول و بهینه‌سازی فراخوانی نهایی است، استفاده کرد. بدون بهینه‌سازی فراخوانی نهایی، می‌توان از تکنیک‌هایی مانند ترامپولین کردن، یعنی استفاده از حلقه‌ای که به‌طور مکرر توابع برگشت‌دهنده‌ی thunk را فراخوانی می‌کند، استفاده کرد. بدون توابع درجه یک، حتی می‌توان در چنین حلقه‌ای فراخوانی‌های نهایی را به فقط گوتوس(gotos، اصطلاح مربوط به فراخوانی‌های نهایی) تبدیل کرد. ترجمه‌های مختلفی وجود دارد که معمولاً به عنوان تبدیل‌های یک انتقاله یا دوانتقاله از محاسبات لامبدای خالص تعریف می‌شوند که عبارات سبک مستقیم را به عبارت CPS تبدیل می‌کنند. زمانی که این روش استفاده می‌شود، معمولاً هدف نوعی تغییر شکل است، مانند کامپایل کردن. برای مثال، در معناشناسی زبانی، کریس بارکر و همکارانش پیشنهاد کرده‌اند که تعیین نشانه‌های جملات با استفاده از CPS ممکن است پدیده‌های خاصی را در زبان طبیعی توضیح دهد. در ریاضیات، ایزومورفیسم کوری-هاروارد بین برنامه‌های کامپیوتری و برهان‌های ریاضی، ترجمه روش "ادامه دهی به روش انتقال پارامتر" را به تنوعی از تعبیه‌های دو نفی منطق کلاسیک به منطق شهودی (سازنده) مرتبط می‌کند. برخلاف ترجمه دو نفی معمولی، که گزاره‌های اتمی پی را به p → ⊥) → ⊥) نگاشت می‌کند، CPS نماد ⊥ را با تایپ عبارت نهایی جایگزین می‌کند. بر این اساس، نتیجه با انتقال تابع همانی به عنوان تداوم عبارت CPS، مانند مثال بالا، به دست می‌آید. | ## جمع‌بندی | منطق کلاسیک به خودی خود مربوط به دستکاری تداوم برنامه‌ها به‌طور مستقیم است، همان‌طور که در عملگر کنترلیِ فراخوانی-با-تداوم-فعلی در اسکیم که مشاهده‌ای به دلیل تیم گریفین(با استفاده از عملگر کنترل سیِ بسیار مربوط) است نیز همین‌گونه است.