سبک ادامه عبور (CPS) روشی برای کنترل جریان کنترل در برنامهنویسی کامپیوتری است که شامل عبور صریح کنترل از طریق یک پارامتر تابع است.
تکامل سبک عبور مداوم (CPS)
خاستگاه سبک ادامه گذراندن را می توان به توسعه علم کامپیوتر نظری ردیابی کرد، و مفهوم استمرار خود ریشه در حساب لامبدا دارد. اولین ذکر صریح "سبک ادامه پاس" به عنوان یک عبارت و استفاده از آن در عمل توسط دانشمند کامپیوتر کریستوفر استراچی در دهه 1960 معرفی شد. در این دوره بود که او و همکارانش در حال بررسی معناشناسی معنایی بودند، چارچوبی برای تعریف معانی زبان های برنامه نویسی.
باز کردن سبک ادامه گذر (CPS)
سبک ادامه گذر (CPS) شکلی از سازماندهی برنامه است که شامل استفاده صریح از ادامه است. ادامه نمایشی از وضعیت یک برنامه کامپیوتری در یک نقطه خاص از زمان است، از جمله پشته فراخوانی و مقادیر متغیرها.
در CPS، هر تابع یک آرگومان اضافی دریافت میکند که معمولاً به نام «cont» یا «k» نامیده میشود، که ادامه برنامه را نشان میدهد – چیزی که پس از اتمام محاسبات تابع باید اتفاق بیفتد. هنگامی که تابع نتیجه خود را محاسبه کرد، به جای برگرداندن آن به روش معمول، این نتیجه را با ارسال آن به ادامه، «برمیگرداند».
این مفهوم را می توان به عنوان راهی برای واضح کردن جریان کنترل در نظر گرفت: به جای انتقال ضمنی کنترل به تماس گیرنده پس از اتمام، یک تابع CPS با فراخوانی ادامه، کنترل را منتقل می کند.
ساختار سبک عبور مداوم (CPS)
در قرارداد سنتی فراخوانی تابع، زمانی که یک تابع فراخوانی می شود، کنترل را با مقدار بازگشتی به تماس گیرنده برمی گرداند. با این حال، در سبک Continuation Passing، کنترل به صراحت از طریق یک پارامتر تابع، که اغلب به عنوان "ادامه" نامیده می شود، منتقل می شود.
ادامه، بقیه محاسبات را نشان می دهد. یعنی زمانی که تابعی یک ادامه دریافت می کند، عملیاتی را انجام می دهد و سپس نتیجه را به ادامه دریافتی منتقل می کند. بنابراین، در سبک ادامه گذر، بازگشت هرگز به طور ضمنی انجام نمی شود.
یک تابع CPS معمولی در یک زبان شبه ممکن است به شکل زیر باشد:
cssfunction add(a, b, continuation) {
result = a + b;
continuation(result);
}
این تابع "افزودن" یک عملیات جمع را انجام می دهد و سپس نتیجه را به ادامه می دهد.
ویژگیهای کلیدی سبک گذراندن ادامهدار (CPS)
-
جریان کنترل صریح: در CPS، جریان کنترل صریح است. هیچ رد پشته پنهانی وجود ندارد و می توانید ترتیب اجرا را به وضوح در کد مشاهده کنید.
-
انعطاف پذیری: از آنجایی که CPS محاسبات را از جریان کنترل جدا می کند، انعطاف پذیری بیشتری برای دستکاری جریان کنترل می دهد.
-
عملیات غیر مسدود کننده: CPS در مدیریت عملیات غیر مسدود یا ناهمزمان بسیار مفید است. می توان از آن برای جلوگیری از جهنم برگشت تماس و مدیریت سناریوهای پیچیده جریان کنترل در کدهای غیر مسدود استفاده کرد.
-
بهینه سازی تماس دم: زبانهایی که از بهینهسازی تماس دنباله پشتیبانی میکنند میتوانند از CPS بهره ببرند، زیرا همه تماسها را به تماسهای دنباله تبدیل میکند، که میتواند از نظر استفاده از حافظه کارآمدتر باشد.
انواع سبک گذراندن ادامه (CPS)
عمدتاً دو نوع ادامه وجود دارد، سبک مستقیم و سبک ادامه پاس. در زیر مقایسه ای بین این دو آورده شده است:
سبک | شرح |
---|---|
سبک مستقیم | در سبک مستقیم، یک تابع اجرای خود را کامل می کند و کنترل را به تابع فراخوانی برمی گرداند. مقدار بازگشتی اغلب یک نتیجه محاسباتی است. |
سبک ادامه گذر | در CPS، تابع یک آرگومان اضافی به نام Continuation دریافت می کند و نتیجه را به این ادامه می دهد. جریان کنترل صریح است. |
استفاده، مشکلات و راه حل ها
CPS بیشتر در زبان های برنامه نویسی کاربردی و در مدیریت عملیات ناهمزمان کاربرد دارد.
-
جاوا اسکریپت ناهمزمان: جاوا اسکریپت، به خصوص در Node.js، از CPS برای مدیریت عملیات غیرانسدادی ناهمزمان استفاده می کند. Callback در جاوا اسکریپت نمونه هایی از CPS هستند.
-
برنامه نویسی تابعی: زبانهایی مانند Scheme و Haskell از CPS برای مدیریت ساختارهای کنترلی مانند حلقهها و مدیریت استثنا استفاده میکنند.
با این حال، CPS می تواند منجر به برخی مشکلات شود:
- خوانایی: CPS گاهی اوقات می تواند به کدهایی منجر شود که به دلیل جهنم برگشت به تماس، خواندن و درک آن سخت است، به خصوص اگر تعداد زیادی تماس تو در تو وجود داشته باشد.
- بهره وری: تبدیل CPS به طور بالقوه می تواند اندازه کد را به دلیل پارامترهای اضافی و فراخوانی تابع افزایش دهد.
راه حل های این مشکلات عبارتند از:
- استفاده کنید وعده ها یا همگام سازی/انتظار در جاوا اسکریپت برای جلوگیری از جهنم پاسخ به تماس و بهبود خوانایی.
- استفاده از زبان های برنامه نویسی که از بهینه سازی tail-call پشتیبانی می کنند می تواند نگرانی های مربوط به کارایی را کاهش دهد.
مقایسه ها
در اینجا یک مقایسه CPS با سایر پارادایم های برنامه نویسی آورده شده است:
پارادایم برنامه نویسی | کنترل جریان | استفاده از مورد |
---|---|---|
سبک گذراندن ادامه (CPS) | صریح، با ادامه. | عملیات غیر مسدود/ناهمزمان، بهینه سازی تماس دنباله. |
سبک مستقیم | ضمنی، تابع به تماس گیرنده برمی گردد. | عملیات همزمان/مسدود کننده |
کوروتین ها | با اجازه دادن به توابع برای توقف و از سرگیری اجرا، چندوظیفه مشترک را انجام دهید. | جریان کنترل پیچیده، چند وظیفه ای مشارکتی. |
چشم اندازهای آینده
CPS همچنان نقش اساسی در ساختار کدهای ناهمزمان به ویژه در جاوا اسکریپت دارد. معرفی async/wait، که شکر نحوی بر روی Promises است، میتواند به عنوان توسعهای نسبت به CPS سنتی، ارائه نحو بهتر و اجتناب از جهنم تماس مجدد دیده شود.
همانطور که برنامه های کاربردی وب و سرور پیچیده تر می شوند و همزمانی اهمیت بیشتری پیدا می کند، CPS و سایر پارادایم های برنامه نویسی ناهمزمان احتمالاً اهمیت بیشتری پیدا می کنند. تحقیقات مداومی در زمینه بهبود زبان های برنامه نویسی و سیستم های زمان اجرا برای پشتیبانی بهتر از این پارادایم ها وجود دارد.
سرورهای پروکسی و CPS
سرورهای پروکسی به عنوان یک واسطه برای درخواست های مشتریانی که به دنبال منابع از سرورهای دیگر هستند عمل می کنند. هنگام رسیدگی به درخواستهای مشتری همزمان، یک سرور پراکسی ممکن است از CPS یا پارادایمهای برنامهنویسی ناهمزمان مشابه برای مدیریت این درخواستها بدون مسدود کردن استفاده کند، بنابراین توان عملیاتی و عملکرد را بهبود میبخشد.