प्रक्रियात्मक पैरामीटर

कम्प्यूटिंग में, एक प्रक्रियात्मक पैरामीटर एक सबरूटीन का एक पैरामीटर (कंप्यूटर विज्ञान) है जो स्वयं एक प्रक्रिया है।

यह अवधारणा एक अत्यंत शक्तिशाली और बहुमुखी कंप्यूटर प्रोग्रामिंग उपकरण है, क्योंकि यह प्रोग्रामर को उस प्रक्रिया के कोड को समझने या संशोधित किए बिना, मनमाने ढंग से जटिल तरीकों से लाइब्रेरी (कंप्यूटर विज्ञान) के कुछ चरणों को संशोधित करने की अनुमति देता है।

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

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

बुनियादी अवधारणा
अधिकांश भाषाओं में जो यह सुविधा प्रदान करती हैं, सबरूटीन पी के एक प्रक्रियात्मक पैरामीटर एफ को पी के शरीर के अंदर बुलाया जा सकता है जैसे कि यह एक सामान्य प्रक्रिया थी:

'प्रक्रिया' पी(एफ): 'वापसी' f(6,3) * f(2,1)

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

'प्रक्रिया' प्लस(x, y): 'वापसी' x + y

तब हम P (प्लस) कह सकते हैं, और परिणाम प्लस(6,3) * प्लस(2,1) = (6 + 3)*(2 + 1) = 27 होगा। दूसरी ओर, यदि हम परिभाषित करते हैं

'प्रक्रिया' quot(u, v): 'वापसी' यू/वी

फिर कॉल P (quot) quot(6,3)*quot(2,1) = (6/3)*(2/1) = 4 लौटाएगा। अंत में, यदि हम परिभाषित करते हैं

'प्रक्रिया' बुराई(z) 'वापसी' z + 100

तब कॉल पी (बुराई) का कोई खास मतलब नहीं होगा, और इसे एक त्रुटि के रूप में चिह्नित किया जा सकता है।

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

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

इन दायरे नियमों का कार्यान्वयन मामूली नहीं है। जब तक actf अंततः निष्पादित हो जाता है, तब तक कॉल स्टैक#स्ट्रक्चर, जहां इसके पर्यावरण चर रहते हैं, स्टैक में मनमाने ढंग से गहरे हो सकते हैं। यह तथाकथित फनर्ग समस्या#डाउनवर्ड्स फनर्ग समस्या है।

उदाहरण: सामान्य प्रविष्टि प्रकार
प्रक्रियात्मक पैरामीटर की अवधारणा को उदाहरणों द्वारा सबसे अच्छी तरह समझाया गया है। एक विशिष्ट अनुप्रयोग सम्मिलन सॉर्ट एल्गोरिदम का निम्नलिखित सामान्य कार्यान्वयन है, जो दो पूर्णांक पैरामीटर ए, बी और दो प्रक्रियात्मक पैरामीटर प्रीक, स्वैप लेता है:

'प्रक्रिया' इसॉर्ट (ए, बी, सटीक, स्वैप): 'पूर्णांक' i, j;    मैं ← ए; 'जबकि' मैं ≤ बी 'करो' जे ← मैं; 'जबकि' j > a 'और' prec(j, j−1) 'do' स्वैप(जे, जे−1); जे ← जे−1; मैं ← मैं+1;

इस प्रक्रिया का उपयोग उपयोगकर्ता द्वारा निर्दिष्ट क्रम में मनमाने डेटाटाइप के कुछ सरणी x के x[a] से x[b] तक तत्वों को क्रमबद्ध करने के लिए किया जा सकता है। पैरामीटर प्री और स्वैप क्लाइंट (प्रोग्रामिंग) द्वारा परिभाषित दो फ़ंक्शन (कंप्यूटिंग) एस होने चाहिए, दोनों ए और बी के बीच दो पूर्णांक आर, एस लेते हैं। प्रीक फ़ंक्शन को 'सही' लौटाना चाहिए यदि और केवल तभी जब क्लाइंट द्वारा परिभाषित क्रम में x[r] में संग्रहीत डेटा x[s] में संग्रहीत डेटा से पहले होना चाहिए। स्वैप फ़ंक्शन को x[r] और x[s] की सामग्री का आदान-प्रदान करना चाहिए, और कोई परिणाम नहीं लौटाना चाहिए।

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

फ़्लोटिंग-पॉइंट संख्याओं को क्रमबद्ध करना
उदाहरण के लिए, हम आइसोर्ट (1, 20,zprec,zswap) को कॉल करके बढ़ते क्रम में 20 फ़्लोटिंग-पॉइंट नंबरों, z[1] से z[20] की एक सरणी z को सॉर्ट कर सकते हैं, जहां फ़ंक्शन zprec और zswap को इस प्रकार परिभाषित किया गया है

'प्रक्रिया' zprec(r, s): 'वापसी' (z[r] < z[s]); 'प्रक्रिया' zswap(r, s): 'फ्लोट' टी; टी ← जेड[आर]; z[r] ← z[s]; z[s] ← t

मैट्रिक्स की पंक्तियों को क्रमबद्ध करना
दूसरे उदाहरण के लिए, मान लीजिए कि M 10 पंक्तियों और 20 स्तंभों वाले पूर्णांकों का एक मैट्रिक्स (कंप्यूटिंग) है, जिसमें सूचकांक 1 से शुरू होते हैं। निम्नलिखित कोड प्रत्येक पंक्ति में तत्वों को पुनर्व्यवस्थित करेगा ताकि सभी सम मान सभी विषम मानों से पहले आएं:

'पूर्णांक' मैं 'प्रक्रिया' eoprec(r, s): 'वापसी' (एम[आई, आर] 'मॉड' 2) < (एम[आई, एस] 'मॉड' 2); 'प्रक्रिया' ईओस्वैप(आर, एस): 'पूर्णांक' टी; टी ← एम[आई,आर]; एम[आई,आर] ← एम[आई,एस]; एम[आई,एस] ← टी; 'के लिए' मैं 1 'से' 10 तक 'करता हूं' आइसोर्ट(1, 20, ईओप्रेक, ईओस्वैप);

ध्यान दें कि eoprec और eoswap का प्रभाव पंक्ति संख्या i पर निर्भर करता है, लेकिन isort प्रक्रिया को यह जानने की आवश्यकता नहीं है।

वेक्टर-सॉर्टिंग प्रक्रिया
निम्नलिखित उदाहरण एक प्रक्रिया वेक्सोर्ट को परिभाषित करने के लिए आइसोर्ट का उपयोग करता है जो एक पूर्णांक n और एक पूर्णांक वेक्टर v को तत्वों v[0] से v[n−1] तक लेता है और उन्हें बढ़ते या घटते क्रम में क्रमबद्ध करता है, यह इस बात पर निर्भर करता है कि तीसरा पैरामीटर incr क्रमशः 'सही' या 'गलत' है या नहीं:

'प्रक्रिया' वेक्सोर्ट(एन, वी, इंसीआर): 'प्रक्रिया' vprec(r, s): 'अगर' बढ़ा 'तो' 'वापसी' v[r]  v[s]; 'प्रक्रिया' vswap(r, s): 'पूर्णांक' टी; टी ← वी[आर]; v[r] ← v[s]; v[s] ← टी isort(0, n−1, vprec, vswap);

फ़ंक्शन vprec प्राप्त करने के लिए नेस्टेड फ़ंक्शन परिभाषाओं के उपयोग पर ध्यान दें, जिसका प्रभाव vecsort को दिए गए पैरामीटर incr पर निर्भर करता है। ऐसी भाषाओं में जो नेस्टेड फ़ंक्शन परिभाषाओं की अनुमति नहीं देती हैं, जैसे मानक सी, इस प्रभाव को प्राप्त करने के लिए जटिल और/या थ्रेड सुरक्षा|थ्रेड-असुरक्षित कोड की आवश्यकता होगी।

उदाहरण: दो अनुक्रमों का विलय
निम्नलिखित उदाहरण अमूर्त डेटा संरचनाओं को उनके ठोस कार्यान्वयन से स्वतंत्र रूप से संसाधित करने के लिए प्रक्रियात्मक मापदंडों के उपयोग को दर्शाता है। समस्या रिकॉर्ड्स के दो ऑर्डर किए गए अनुक्रमों को एक एकल क्रमबद्ध अनुक्रम में विलय करने की है, जहां क्लाइंट द्वारा रिकॉर्ड्स की प्रकृति और ऑर्डरिंग मानदंड को चुना जा सकता है। निम्नलिखित कार्यान्वयन केवल यह मानता है कि प्रत्येक रिकॉर्ड को एक मेमोरी पते द्वारा संदर्भित किया जा सकता है, और एक शून्य पता Λ है जो किसी भी वैध रिकॉर्ड का पता नहीं है। क्लाइंट को प्रत्येक क्रम में पहले रिकॉर्ड के ए, बी पते और बाद में वर्णित किए जाने वाले फ़ंक्शन प्री, नेक्स्ट और अपेंड प्रदान करने होंगे।

'प्रक्रिया' मर्ज (ए, बी, सटीक, अगलाए, परिशिष्टए, अगलाबी, परिशिष्टबी): 'पता' आईएनआई, फिन, टी ini ← Λ; फिन ← Λ 'जबकि' A ≠ Λ या B ≠ Λ 'करें' 'यदि' B = Λ 'या' (A ≠ Λ 'और' B ≠ Λ 'और' prec(A, B)) 'तब' t ← अगलाA(A) फिन ← परिशिष्टए(ए, फिन); 'अगर' आईएनआई = Λ 'तब' आईएनआई ← फिन ए ← टी 'अन्य' t ← अगलाB(B) फिन ← एपेंडबी(बी, फिन); 'अगर' आईएनआई = Λ 'तब' आईएनआई ← फिन बी ← टी 'वापसी' ini

फ़ंक्शन प्रीक को दो रिकॉर्ड्स के पते r, s लेना चाहिए, प्रत्येक अनुक्रम से एक, और आउटपुट अनुक्रम में पहला रिकॉर्ड दूसरे से पहले आने पर 'सही' लौटाना चाहिए। फ़ंक्शन नेक्स्टए को पहले अनुक्रम से एक रिकॉर्ड का पता लेना चाहिए, और उसी क्रम में अगले रिकॉर्ड का पता लौटाना चाहिए, या यदि कोई नहीं है तो Λ लौटाना चाहिए। फ़ंक्शन एपेंडए को अनुक्रम ए से आउटपुट अनुक्रम में पहला रिकॉर्ड जोड़ना चाहिए; इसके तर्क जोड़े जाने वाले रिकॉर्ड का पता A और आउटपुट सूची के अंतिम रिकॉर्ड का पता फिन (या यदि वह सूची अभी भी खाली है) हैं। प्रक्रिया परिशिष्ट को आउटपुट सूची के अंतिम तत्व का अद्यतन पता वापस करना चाहिए। नेक्स्टबी और एपेंडबी प्रक्रियाएं अन्य इनपुट अनुक्रम के अनुरूप हैं।

लिंक की गई सूचियों का विलय
सामान्य मर्ज प्रक्रिया के उपयोग को स्पष्ट करने के लिए, यहां दो सरल लिंक की गई सूचियों को मर्ज करने के लिए कोड दिया गया है, जो पते आर, एस पर नोड्स से शुरू होती है। यहां हम मानते हैं कि प्रत्येक रिकॉर्ड x में एक पूर्णांक फ़ील्ड x.INFO और एक पता फ़ील्ड x.NEXT होता है जो अगले नोड को इंगित करता है; जहां प्रत्येक सूची में सूचना फ़ील्ड बढ़ते क्रम में हैं। मर्ज द्वारा इनपुट सूचियों को नष्ट कर दिया जाता है, और उनके नोड्स का उपयोग आउटपुट सूची बनाने के लिए किया जाता है।

'प्रक्रिया' सूची मर्ज (आर, एस): 'प्रक्रिया' पूर्व(आर, एस): 'वापसी' r.INFO < s.INFO 'प्रक्रिया' अगला(x): 'वापसी' x.अगला 'प्रक्रिया' परिशिष्ट (एक्स, फिन) 'अगर' फिन ≠ Λ 'तो' फिन.अगला ← एक्स x.अगला ← Λ 'वापसी' एक्स 'वापसी' मर्ज (आर, एस, सटीक, अगला, जोड़ें, अगला, जोड़ें)

वेक्टरों का विलय
निम्नलिखित कोड अनुक्रमों के वास्तविक प्रतिनिधित्व से सामान्य मर्ज प्रक्रिया की स्वतंत्रता को दर्शाता है। यह दो साधारण सरणियों U[0] से U[m−1] और V[0] से V[n−1] तक फ्लोटिंग-पॉइंट संख्याओं के तत्वों को घटते क्रम में मिलाता है। इनपुट सरणियों को संशोधित नहीं किया गया है, और मानों का मर्ज किया गया अनुक्रम W[m+n−1] के माध्यम से तीसरे वेक्टर W[0] में संग्रहीत किया जाता है। जैसा कि सी प्रोग्रामिंग भाषा में है, हम मानते हैं कि अभिव्यक्ति &V वेरिएबल V का पता देता है, *p वह वेरिएबल देता है जिसका पता p का मान है, और &(X[i]) किसी भी सरणी X और किसी पूर्णांक i के लिए &(X[0]) + i के बराबर है।

'प्रक्रिया' सरणीमर्ज (यू, एम, वी, एन, डब्ल्यू): 'प्रक्रिया' पूर्व(आर, एस): 'वापसी' (*r) > (*s) 'प्रक्रिया' अगलाU(x): 'अगर' x = &(U[m−1]) 'तो' 'वापसी' Λ 'अन्यथा' 'वापसी' x + 1 'प्रक्रिया' अगलाV(x): 'अगर' x = &(V[n−1]) 'तो' 'वापसी' Λ 'अन्यथा' 'वापसी' x + 1 'प्रक्रिया' परिशिष्ट (एक्स, फिन) 'if' fin = Λ 'then' fin ← &(W[0]) (*फिन) ← (*x) 'वापसी' फिन + 1 'यदि' m = 0 तो U ← Λ 'यदि' n = 0 तो V ← Λ 'वापसी' मर्ज (यू, वी, प्रीक, नेक्स्टयू, अपेंड, नेक्स्टवी, अपेंड)

एक अंतराल पर एकीकृत करना
निम्नलिखित प्रक्रिया अनुमानित अभिन्न (गणित) की गणना करती है $$\textstyle\int_a^b$$ वास्तविक संख्या के दिए गए अंतराल [ए,बी] पर किसी दिए गए वास्तविक-मूल्यवान फ़ंक्शन (गणित) का एफ (एक्स) डीएक्स। उपयोग की जाने वाली संख्यात्मक विधि चरणों की दी गई संख्या n के साथ ट्रैपेज़ियम नियम है; वास्तविक संख्याएँ फ़्लोटिंग-पॉइंट संख्याओं द्वारा अनुमानित की जाती हैं।

'प्रक्रिया' Intg(f, a, b, n): 'फ्लोट' टी, एक्स, एस; 'पूर्णांक' मैं 'अगर' बी = ए 'तो' 'वापसी' 0 एक्स ← ए; s ← f(a) / 2; 'के लिए' i 'से' 1 'से' n−1 'करें' t ← i/(n+1); x ← (1−t) * a + t * b;        s ← s + f(x) s ← f(b) / 2 'वापसी' (बी - ए) * एस / एन

डिस्क पर एकीकरण
अब किसी दिए गए फ़ंक्शन को एकीकृत करने की समस्या पर विचार करें $$g$$, दो तर्कों के साथ, एक डिस्क पर $$D$$ दिए गए केंद्र के साथ ($$xc,yc$$) और त्रिज्या दी गई है $$R$$. चर के परिवर्तन से इस समस्या को दो नेस्टेड एकल-चर इंटीग्रल में कम किया जा सकता है


 * $$\int\!\int_D g(x,y)\, \mathrm{d}x\, \mathrm{d}y = \int_0^R z   \left(\int_0^{2\pi} g(\mathit{xc}+z \cos t ,\mathit{yc}+z \sin t ) \,\mathrm{d}t\right)\,\mathrm{d}z$$

निम्नलिखित कोड एक समीकरण के पक्षों को लागू करता है|दाहिने हाथ का सूत्र:

प्रक्रिया DiskIntg(g, xc, yc, R, n) प्रक्रिया gring(z): प्रक्रिया जीपोलर(टी): फ़्लोट x, y x ← xc + z * cos(t) y ← yc + z * sin(t) वापसी जी(एक्स, वाई) पूर्णांक m ← गोल(n*z/R) वापसी z * Intg(gpolar, 0, 2*π, m) वापसी इंटग(ग्रिंग, 0, आर, एन)

यह कोड दो स्तरों में एकीकरण प्रक्रिया Intg का उपयोग करता है। बाहरी स्तर (अंतिम पंक्ति) के अभिन्न अंग की गणना करने के लिए Intg का उपयोग करता है $$gring(z)$$ के लिए $$z$$ 0 से भिन्न होता है $$R$$. आंतरिक स्तर (अंतिम से अगली पंक्ति) परिभाषित करता है $$gring(z)$$ का अभिन्न अंग होने के नाते $$g(x,y)$$ केंद्र वाले वृत्त के ऊपर $$(xc,yc)$$ और त्रिज्या $$z$$.

इतिहास
प्रक्रियात्मक मापदंडों का आविष्कार इलेक्ट्रॉनिक कंप्यूटर के युग से पहले, गणितज्ञ अलोंजो चर्च द्वारा, गणना के उनके लैम्ब्डा कैलकुलस मॉडल के हिस्से के रूप में किया गया था।

प्रोग्रामिंग भाषा सुविधा के रूप में प्रक्रियात्मक पैरामीटर ALGOL 60 प्रोग्रामिंग भाषा द्वारा पेश किए गए थे। वास्तव में, ALGOL 60 में नाम पैरामीटर-पासिंग तंत्र द्वारा एक शक्तिशाली कॉल था जो प्रक्रियात्मक पैरामीटर के कुछ उपयोगों को सरल बना सकता था; जेन्सेन का उपकरण देखें।

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

यह भी देखें

 * फ़ंक्शन सूचक
 * कार्यात्मक प्रोग्रामिंग
 * फनर्ग समस्या
 * डिज़ाइन पैटर्न (कंप्यूटर विज्ञान)

श्रेणी:सबरूटीन्स