निरंतर-अग्रगामी शैली (सीपीएस)

कार्यात्मक प्रोग्रामिंग में, निरंतरता-पासिंग शैली (सीपीएस) प्रोग्रामिंग की एक शैली है जिसमें नियंत्रण प्रवाह को निरंतरता के रूप में स्पष्ट रूप से पारित किया जाता है। इसकी तुलना प्रत्यक्ष शैली से की जाती है, जो प्रोग्रामिंग की सामान्य शैली है। गेराल्ड जे सुसमैन और गाइ एल. स्टील, जूनियर ने एआई मेमो 349 (1975) में वाक्यांश गढ़ा, जो स्कीम (प्रोग्रामिंग भाषा) प्रोग्रामिंग भाषा का पहला संस्करण निर्धारित करता है। जॉन सी. रेनॉल्ड्स निरंतरता की अनेक खोजों का विस्तृत विवरण देते हैं। निरंतरता-पासिंग शैली में लिखा गया एक फ़ंक्शन एक अतिरिक्त तर्क लेता है: एक स्पष्ट निरंतरता; यानी, एक तर्क का एक कार्य। जब सीपीएस फ़ंक्शन ने अपने परिणाम मान की गणना की है, तो यह तर्क के रूप में इस मान के साथ निरंतरता फ़ंक्शन को कॉल करके इसे वापस कर देता है। इसका मतलब यह है कि सीपीएस फ़ंक्शन को लागू करते समय, कॉलिंग फ़ंक्शन को सबरूटीन के रिटर्न वैल्यू के साथ लागू करने के लिए एक प्रक्रिया प्रदान करने की आवश्यकता होती है। कोड को इस रूप में व्यक्त करने से कई चीजें स्पष्ट हो जाती हैं जो प्रत्यक्ष शैली में अंतर्निहित होती हैं। इनमें शामिल हैं: प्रक्रिया रिटर्न, जो निरंतरता के लिए कॉल के रूप में स्पष्ट हो जाते हैं; मध्यवर्ती मान, जो सभी दिए गए नाम हैं; तर्क मूल्यांकन का क्रम, जिसे स्पष्ट किया गया है; और पूंछ कॉल, जो बस उसी निरंतरता के साथ एक प्रक्रिया को कॉल करते हैं, असंशोधित, जो कॉलर को दी गई थी।

प्रोग्राम को स्वचालित रूप से डायरेक्ट स्टाइल से सीपीएस में बदला जा सकता है। कार्यात्मक और तर्क प्रोग्रामिंग कंपाइलर अक्सर सीपीएस को एक मध्यवर्ती प्रतिनिधित्व के रूप में उपयोग करते हैं जहां एक अनिवार्य प्रोग्रामिंग या प्रक्रियात्मक प्रोग्रामिंग प्रोग्रामिंग भाषा के लिए एक कंपाइलर स्थिर एकल असाइनमेंट फॉर्म (एसएसए) का उपयोग करेगा। एसएसए औपचारिक रूप से सीपीएस के सबसेट के बराबर है (गैर-स्थानीय नियंत्रण प्रवाह को छोड़कर, जो तब नहीं होता है जब सीपीएस को मध्यवर्ती प्रतिनिधित्व के रूप में उपयोग किया जाता है)। कार्यात्मक संकलक  सीपीएस में 'थंक (विलंबित गणना)' (नीचे दिए गए उदाहरणों में वर्णित) के बजाय ए-सामान्य फॉर्म (एएनएफ) (लेकिन केवल उत्सुक मूल्यांकन की आवश्यकता वाली भाषाओं के लिए) का उपयोग कर सकते हैं। सीपीएस का उपयोग स्थानीय या वैश्विक शैली के रूप में प्रोग्रामर की तुलना में कंपाइलरों द्वारा अधिक बार किया जाता है।

उदाहरण
सीपीएस में, प्रत्येक प्रक्रिया एक अतिरिक्त तर्क लेती है जो दर्शाती है कि फ़ंक्शन द्वारा गणना किए जा रहे परिणाम के साथ क्या किया जाना चाहिए। यह, आमतौर पर उपलब्ध विभिन्न प्रकार के निर्माणों को प्रतिबंधित करने वाली एक प्रतिबंधात्मक शैली के साथ, कार्यक्रमों के शब्दार्थ को उजागर करने के लिए उपयोग किया जाता है, जिससे उनका विश्लेषण करना आसान हो जाता है। यह शैली असामान्य नियंत्रण संरचनाओं को व्यक्त करना भी आसान बनाती है, जैसे पकड़ना/फेंकना या नियंत्रण के अन्य गैर-स्थानीय हस्तांतरण।

सीपीएस की कुंजी यह याद रखना है कि (ए) प्रत्येक फ़ंक्शन एक अतिरिक्त तर्क लेता है जिसे इसकी निरंतरता के रूप में जाना जाता है, और (बी) फ़ंक्शन कॉल में प्रत्येक तर्क या तो एक चर या लैम्ब्डा (प्रोग्रामिंग) होना चाहिए (अधिक जटिल अभिव्यक्ति नहीं)। इसमें अभिव्यक्ति को अंदर-बाहर करने का प्रभाव होता है क्योंकि अभिव्यक्ति के सबसे अंदरूनी हिस्सों का मूल्यांकन पहले किया जाना चाहिए, इस प्रकार सीपीएस मूल्यांकन के क्रम के साथ-साथ नियंत्रण प्रवाह को भी स्पष्ट करता है। प्रत्यक्ष शैली में कोड और संबंधित सीपीएस के कुछ उदाहरण नीचे दिखाई देते हैं। ये उदाहरण योजना (प्रोग्रामिंग भाषा) में लिखे गए हैं; परंपरा के अनुसार निरंतरता फ़ंक्शन को नामित पैरामीटर के रूप में दर्शाया जाता है : ध्यान दें कि सीपीएस संस्करणों में, आदिम का उपयोग किया जाता है, जैसे  और   स्वयं सीपीएस हैं, प्रत्यक्ष शैली नहीं, इसलिए उपरोक्त उदाहरणों को एक योजना प्रणाली में काम करने के लिए हमें आदिम के इन सीपीएस संस्करणों को लिखने की आवश्यकता होगी, उदाहरण के लिए   द्वारा परिभाषित: सामान्य तौर पर ऐसा करने के लिए, हम एक रूपांतरण रूटीन लिख सकते हैं: सीपीएस में लिखी गई प्रक्रिया को प्रत्यक्ष शैली में लिखी गई प्रक्रिया से कॉल करने के लिए, एक निरंतरता प्रदान करना आवश्यक है जो सीपीएस प्रक्रिया द्वारा गणना किए गए परिणाम प्राप्त करेगी। उपरोक्त उदाहरण में (यह मानते हुए कि सीपीएस प्राइमेटिव्स प्रदान किए गए हैं), हम कॉल कर सकते हैं.

सीपीएस में आदिम कार्य प्रदान करने के तरीके में कंपाइलरों के बीच कुछ विविधता है। ऊपर हमने सबसे सरल सम्मेलन का उपयोग किया है, हालांकि कभी-कभी बूलियन प्राइमेटिव प्रदान किए जाते हैं जो दो संभावित मामलों में कॉल करने के लिए दो थंक (विलंबित गणना) लेते हैं, इसलिए  अंदर बुलाओ   उपरोक्त परिभाषा के स्थान पर इस प्रकार लिखा जाएगा. इसी तरह, कभी-कभी  प्रिमिटिव स्वयं सीपीएस में शामिल नहीं है, बल्कि एक फ़ंक्शन है   प्रदान किया जाता है जिसमें तीन तर्क होते हैं: एक बूलियन स्थिति और सशर्त की दो भुजाओं के अनुरूप दो थंक।

ऊपर दिखाए गए अनुवाद बताते हैं कि सीपीएस एक वैश्विक परिवर्तन है। जैसी कि अपेक्षा की जा सकती है, प्रत्यक्ष शैली का फैक्टोरियल एक ही तर्क लेता है; सीपीएस फैक्टोरियल दो लेता है: तर्क और एक निरंतरता। सीपीएस-एड फ़ंक्शन को कॉल करने वाले किसी भी फ़ंक्शन को या तो एक नई निरंतरता प्रदान करनी होगी या अपना स्वयं का पास करना होगा; सीपीएस-एड फ़ंक्शन से गैर-सीपीएस फ़ंक्शन में कोई भी कॉल अंतर्निहित निरंतरता का उपयोग करेगी। इस प्रकार, फ़ंक्शन स्टैक की पूर्ण अनुपस्थिति सुनिश्चित करने के लिए, संपूर्ण प्रोग्राम CPS में होना चाहिए।

हास्केल में सीपीएस (प्रोग्रामिंग भाषा)
इस अनुभाग में हम एक फ़ंक्शन लिखेंगे  जो पाइथागोरस प्रमेय का उपयोग करके कर्ण की गणना करता है। का एक पारंपरिक कार्यान्वयन   फ़ंक्शन इस तरह दिखता है: पारंपरिक फ़ंक्शन को सीपीएस में बदलने के लिए, हमें इसके हस्ताक्षर को बदलने की आवश्यकता है। फ़ंक्शन को फ़ंक्शन प्रकार का एक और तर्क मिलेगा, और इसका रिटर्न प्रकार उस फ़ंक्शन पर निर्भर करता है: सबसे पहले हम a के वर्ग की गणना करते हैं  फ़ंक्शन और एक लैम्ब्डा फ़ंक्शन को निरंतरता के रूप में पास करें जो पहले तर्क के रूप में ए के एक वर्ग को स्वीकार करेगा। और इसी तरह जब तक हम अपनी गणना के नतीजे पर नहीं पहुंच जाते। इस फ़ंक्शन का परिणाम प्राप्त करने के लिए हम पास हो सकते हैं   अंतिम तर्क के रूप में कार्य करता है जो उसे दिए गए मान को अपरिवर्तित लौटाता है:.

एमटीएल लाइब्रेरी, जिसे ग्लासगो हास्केल कंपाइलर के साथ भेजा जाता है, में मॉड्यूल है. यह मॉड्यूल कॉन्ट प्रकार प्रदान करता है, जो मोनाड और कुछ अन्य उपयोगी कार्यों को लागू करता है। निम्नलिखित स्निपेट दिखाता है  जारी का उपयोग कर कार्य करें: न केवल सिंटैक्स साफ़ हो गया है, बल्कि यह प्रकार हमें फ़ंक्शन का उपयोग करने की अनुमति देता है  प्रकार के साथ. इस फ़ंक्शन में फ़ंक्शन प्रकार का एक तर्क होता है; वह फ़ंक्शन तर्क फ़ंक्शन को भी स्वीकार करता है, जो उसके कॉल के बाद होने वाली सभी गणनाओं को छोड़ देता है। उदाहरण के लिए, आइए इसके निष्पादन को तोड़ें  फ़ंक्शन यदि इसका कम से कम एक तर्क नकारात्मक है तो शून्य लौट रहा है:

वस्तुओं के रूप में निरंतरता
निरंतरता के साथ प्रोग्रामिंग तब भी उपयोगी हो सकती है जब कोई कॉल करने वाला कॉल पूरा होने तक इंतजार नहीं करना चाहता। उदाहरण के लिए, यूजर-इंटरफ़ेस (यूआई) प्रोग्रामिंग में, एक रूटीन डायलॉग बॉक्स फ़ील्ड सेट कर सकता है और इन्हें निरंतरता फ़ंक्शन के साथ यूआई फ्रेमवर्क में पास कर सकता है। यह कॉल तुरंत वापस आती है, जिससे एप्लिकेशन कोड तब तक जारी रहता है जब तक उपयोगकर्ता डायलॉग बॉक्स के साथ इंटरैक्ट करता है। एक बार जब उपयोगकर्ता ओके बटन दबाता है, तो फ्रेमवर्क अद्यतन फ़ील्ड के साथ निरंतरता फ़ंक्शन को कॉल करता है। हालाँकि कोडिंग की यह शैली निरंतरता का उपयोग करती है, यह पूर्ण सीपीएस नहीं है।

एक समान विचार का उपयोग तब किया जा सकता है जब फ़ंक्शन को किसी भिन्न थ्रेड में या किसी भिन्न प्रोसेसर पर चलाना होगा। फ्रेमवर्क वर्कर थ्रेड में कॉल किए गए फ़ंक्शन को निष्पादित कर सकता है, फिर वर्कर के परिणामों के साथ मूल थ्रेड में निरंतरता फ़ंक्शन को कॉल कर सकता है। यह स्विंग (जावा) यूआई फ्रेमवर्क का उपयोग करके जावा (प्रोग्रामिंग भाषा) 8 में है:

टेल कॉल
सीपीएस में प्रत्येक कॉल एक टेल कॉल है, और निरंतरता स्पष्ट रूप से पारित की जाती है। टेल कॉल अनुकूलन (टीसीओ) के बिना सीपीएस का उपयोग करने से रिकर्सन के दौरान न केवल निर्मित निरंतरता संभावित रूप से बढ़ेगी, बल्कि कॉल स्टैक भी बढ़ेगा। यह आमतौर पर अवांछनीय है, लेकिन इसका उपयोग दिलचस्प तरीकों से किया गया है - चिकन (योजना कार्यान्वयन)#डिज़ाइन कंपाइलर देखें। चूंकि सीपीएस और टीसीओ एक अंतर्निहित फ़ंक्शन रिटर्न की अवधारणा को समाप्त करते हैं, उनका संयुक्त उपयोग रन-टाइम स्टैक की आवश्यकता को समाप्त कर सकता है। कार्यात्मक प्रोग्रामिंग भाषाओं के लिए कई कंपाइलर और दुभाषिए नए तरीकों से इस क्षमता का उपयोग करते हैं।

उपयोग और कार्यान्वयन
निरंतरता पासिंग शैली का उपयोग एक कार्यात्मक भाषा में निरंतरता को लागू करने और प्रवाह ऑपरेटरों को नियंत्रित करने के लिए किया जा सकता है जिसमें प्रथम श्रेणी की निरंतरता की सुविधा नहीं है लेकिन प्रथम श्रेणी के फ़ंक्शन और टेल-कॉल अनुकूलन हैं। टेल-कॉल ऑप्टिमाइज़ेशन के बिना, ट्रैम्पोलिन (कंप्यूटर) जैसी तकनीकों का उपयोग किया जा सकता है, यानी एक लूप का उपयोग करना जो पुनरावृत्त रूप से थंक (कार्यात्मक प्रोग्रामिंग)-रिटर्निंग फ़ंक्शंस को आमंत्रित करता है; प्रथम श्रेणी के फ़ंक्शंस के बिना, ऐसे लूप में टेल कॉल को केवल गोटो में परिवर्तित करना भी संभव है।

सीपीएस में कोड लिखना, हालांकि असंभव नहीं है, अक्सर त्रुटि-प्रवण होता है। विभिन्न अनुवाद हैं, जिन्हें आमतौर पर शुद्ध लैम्ब्डा कैलकुलस के एक या दो-पास रूपांतरण के रूप में परिभाषित किया जाता है, जो प्रत्यक्ष शैली अभिव्यक्तियों को सीपीएस अभिव्यक्तियों में परिवर्तित करता है। हालाँकि, ट्रम्पोलिन्ड शैली में लिखना अत्यंत कठिन है; जब उपयोग किया जाता है, तो यह आमतौर पर किसी प्रकार के परिवर्तन का लक्ष्य होता है, जैसे कि कंपाइलर।

एक से अधिक निरंतरता का उपयोग करने वाले कार्यों को विभिन्न नियंत्रण प्रवाह प्रतिमानों को पकड़ने के लिए परिभाषित किया जा सकता है, उदाहरण के लिए (स्कीम (प्रोग्रामिंग भाषा) में): यह ध्यान देने वाली बात है कि सीपीएस परिवर्तन वैचारिक रूप से एक योनेडा एम्बेडिंग है। यह π-कैलकुलस में लैम्ब्डा कैलकुलस के एम्बेडिंग के समान है।

अन्य क्षेत्रों में उपयोग करें
कंप्यूटर विज्ञान के बाहर, सरल अभिव्यक्तियों को जटिल अभिव्यक्तियों में लिखने की पारंपरिक पद्धति के विकल्प के रूप में सीपीएस अधिक सामान्य रुचि का है। उदाहरण के लिए, भाषाई शब्दार्थ के अंतर्गत, क्रिस बार्कर (भाषाविद्) और उनके सहयोगियों ने सुझाव दिया है कि सीपीएस का उपयोग करके वाक्यों के अर्थ निर्दिष्ट करने से प्राकृतिक भाषा में कुछ घटनाओं की व्याख्या हो सकती है। गणित में, कंप्यूटर प्रोग्राम और गणितीय प्रमाणों के बीच करी-हावर्ड समरूपता, निरंतरता-पासिंग शैली अनुवाद को अंतर्ज्ञानवादी तर्क में शास्त्रीय तर्क के दोहरे-नकारात्मक एम्बेडिंग की विविधता से संबंधित करती है|अंतर्ज्ञानवादी (रचनात्मक) तर्क। नियमित दोहरे-नकारात्मक अनुवाद के विपरीत, जो परमाणु प्रस्तावों p को ((p → ⊥) → ⊥) में मैप करता है, निरंतरता पासिंग शैली अंतिम अभिव्यक्ति के प्रकार से ⊥ को प्रतिस्थापित करती है। तदनुसार, उपरोक्त उदाहरण के अनुसार, सीपीएस अभिव्यक्ति की निरंतरता के रूप में पहचान फ़ंक्शन को पारित करके परिणाम प्राप्त किया जाता है।

शास्त्रीय तर्क स्वयं कार्यक्रमों की निरंतरता में सीधे हेरफेर करने से संबंधित है, जैसा कि स्कीम के कॉल-विथ-वर्तमान-निरंतरता नियंत्रण ऑपरेटर में, टिम ग्रिफिन (निकट से संबंधित सी नियंत्रण ऑपरेटर का उपयोग करके) के कारण एक अवलोकन है।

यह भी देखें

 * पूंछ प्रत्यावर्तन#ट्रैम्पोलिनिंग के माध्यम से

संदर्भ

 * Continuation Passing C (CPC) - programming language for writing concurrent systems, designed and developed by Juliusz Chroboczek and Gabriel Kerneis. github repository
 * The construction of a CPS-based compiler for ML is described in:
 * Chicken Scheme compiler, a Scheme to C compiler that uses continuation-passing style for translating Scheme procedures into C functions while using the C-stack as the nursery for the generational garbage collector
 * Direct link: "Section 3.4. Continuation Passing Style".
 * Direct link: "Section 3.4. Continuation Passing Style".
 * Direct link: "Section 3.4. Continuation Passing Style".
 * Direct link: "Section 3.4. Continuation Passing Style".
 * Direct link: "Section 3.4. Continuation Passing Style".