फ़ंक्शन (कंप्यूटर प्रोग्रामिंग)

From Vigyanwiki


कंप्यूटर प्रोग्रामिंग में, एक फ़ंक्शन या सबरूटीन निर्देश (कंप्यूटर विज्ञान) का एक अनुक्रम है जो एक इकाई के रूप में पैक किया गया एक विशिष्ट कार्य करता है। इस इकाई का उपयोग उन कार्यक्रमों में किया जा सकता है जहां वह विशेष कार्य किया जाना चाहिए।

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

सबरूटीन के विचार की कल्पना सबसे पहले जॉन मौचली और कैथलीन एंटोनेली ने ENIAC पर अपने काम के दौरान की थी,[2] और ईडीवीएसी-प्रकार की मशीनों के लिए समस्याओं की तैयारी पर जनवरी 1947 में हार्वर्ड संगोष्ठी में रिकॉर्ड किया गया।[3] मौरिस विल्केस, डेविड व्हीलर (ब्रिटिश कंप्यूटर वैज्ञानिक) और स्टेनली गिल को आम तौर पर इस अवधारणा के औपचारिक आविष्कार का श्रेय दिया जाता है, जिसे उन्होंने एक बंद उप-दिनचर्या कहा है,[4][5] एक खुले सबरूटीन या मैक्रो (कंप्यूटर विज्ञान) के साथ तुलना।[6] हालाँकि, एलन ट्यूरिंग ने 1945 के एक पेपर में एनपीएल स्वचालित कंप्यूटिंग इंजन के डिजाइन प्रस्तावों पर सबरूटीन्स पर चर्चा की थी, यहां तक ​​कि कॉल स्टैक की अवधारणा का आविष्कार भी किया था।[7] फ़ंक्शंस एक शक्तिशाली प्रोग्रामिंग टूल हैं,[8] और कई प्रोग्रामिंग भाषाओं के सिंटैक्स (प्रोग्रामिंग भाषाओं) में सबरूटीन्स को लिखने और उपयोग करने के लिए समर्थन शामिल है। कार्यों का विवेकपूर्ण उपयोग (उदाहरण के लिए, संरचित प्रोग्रामिंग दृष्टिकोण के माध्यम से) अक्सर एक बड़े कार्यक्रम को विकसित करने और बनाए रखने की लागत को काफी हद तक कम कर देगा, जबकि इसकी गुणवत्ता और विश्वसनीयता में वृद्धि होगी।[9] फ़ंक्शंस, जिन्हें अक्सर पुस्तकालयों में एकत्र किया जाता है, सॉफ़्टवेयर साझा करने और व्यापार करने के लिए एक महत्वपूर्ण तंत्र हैं। ऑब्जेक्ट ओरिएंटेड प्रोग्रामिंग का अनुशासन ऑब्जेक्ट (कंप्यूटर विज्ञान) और विधियों (जो इन ऑब्जेक्ट या ऑब्जेक्ट कक्षा (कंप्यूटर प्रोग्रामिंग) से जुड़े फ़ंक्शन हैं) पर आधारित है।

मुख्य अवधारणाएँ

किसी फ़ंक्शन की सामग्री उसका निकाय है, जो प्रोग्राम कोड का टुकड़ा है जिसे फ़ंक्शन को कॉल करने या लागू करने पर निष्पादित किया जाता है।

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

Convention Description Common use
Call by value Argument is evaluated and copy of the value is passed to function Default in most Algol-like languages after Algol 60, such as Pascal, Delphi, Simula, CPL, PL/M, Modula, Oberon, Ada, and many others. C, C++, Java (References to objects and arrays are also passed by value)
Call by reference Reference to an argument, typically its address is passed Selectable in most Algol-like languages after Algol 60, such as Algol 68, Pascal, Delphi, Simula, CPL, PL/M, Modula, Oberon, Ada, and many others. C++, Fortran, PL/I
Call by result Parameter value is copied back to argument on return from the function Ada OUT parameters
Call by value-result Parameter value is copied back on entry to the function and again on return Algol, Swift in-out parameters
Call by name Like a macro – replace the parameters with the unevaluated argument expressions, then evaluate the argument in the context of the caller every time that the called routine uses the parameter. Algol, Scala
Call by constant value Like call by value except that the parameter is treated as a constant PL/I NONASSIGNABLE parameters, Ada IN parameters

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

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

एक फ़ंक्शन जिसका उद्देश्य एक बूलियन-मूल्य वाले फ़ंक्शन की गणना करना है (अर्थात हां/नहीं प्रश्न का उत्तर देना) कभी-कभी विधेय कहा जाता है। तर्क प्रोग्रामिंग भाषाओं में, अक्सर[vague] सभी कार्यों को विधेय कहा जाता है, क्योंकि वे मुख्य रूप से हैं[vague] सफलता या विफलता का निर्धारण करें।[citation needed]

एक फ़ंक्शन जो कोई मान नहीं लौटाता या शून्य मान लौटाता है उसे कभी-कभी प्रक्रिया कहा जाता है। प्रक्रियाएं आमतौर पर अपने तर्कों को संशोधित करती हैं और प्रक्रियात्मक प्रोग्रामिंग का एक मुख्य हिस्सा हैं।

शब्दावली

सबरूटीन एक ऐसा फ़ंक्शन है जो कोई मान नहीं लौटाता है।[10] फ़ंक्शंस का प्राथमिक उद्देश्य जटिल गणनाओं को सार्थक भागों में विभाजित करना और उन्हें नाम देना है। रेफरी नाम = स्ट्रॉस्ट्रुप-ch12-306 >Stroustrup, Bjarne (2013). C++ प्रोग्रामिंग भाषा, चौथा संस्करण. Addison-Wesley. p. 307. ISBN 978-0-321-56384-2.</ref> फ़ंक्शन अपने कॉलर को एक परिकलित मान (इसका रिटर्न मान) लौटा सकता है, या विभिन्न परिणाम मान या आउटपुट पैरामीटर प्रदान कर सकता है। दरअसल, फ़ंक्शन का एक सामान्य उपयोग फ़ंक्शन (गणित) को कार्यान्वित करना है, जिसमें फ़ंक्शन का उद्देश्य पूरी तरह से एक या अधिक परिणामों की गणना करना है जिनके मान पूरी तरह से फ़ंक्शन में दिए गए तर्कों द्वारा निर्धारित होते हैं। (उदाहरणों में किसी संख्या के लघुगणक या मैट्रिक्स (गणित) के निर्धारक की गणना शामिल हो सकती है।) कुछ भाषाओं में एक प्रक्रिया के लिए सिंटैक्स जो एक मान लौटाता है, अनिवार्य रूप से उस प्रक्रिया के लिए सिंटैक्स के समान होता है जो एक मान नहीं लौटाता है, उदाहरण के लिए, रिटर्न खंड की अनुपस्थिति को छोड़कर। कुछ भाषाओं में एक प्रक्रिया अपने तर्कों के आधार पर गतिशील रूप से मूल्य के साथ या उसके बिना वापस लौटने का विकल्प चुन सकती है।

भाषा समर्थन

उच्च-स्तरीय प्रोग्रामिंग भाषाओं में आमतौर पर विशिष्ट निर्माण शामिल होते हैं:

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

कुछ प्रोग्रामिंग भाषाएं, जैसे पास्कल (प्रोग्रामिंग भाषा), फोरट्रान, एडा (प्रोग्रामिंग भाषा) और बुनियादी की कई बोली (कंप्यूटिंग), फ़ंक्शन या फ़ंक्शन उपप्रोग्राम के बीच अंतर करती हैं, जो कॉलिंग प्रोग्राम और सबरूटीन या प्रक्रियाओं के लिए एक स्पष्ट रिटर्न मान प्रदान करती हैं। , जो नहीं है. उन भाषाओं में, फ़ंक्शन कॉल सामान्यतः अभिव्यक्ति (प्रोग्रामिंग) में एम्बेडेड होते हैं (उदाहरण के लिए, a sqrt फ़ंक्शन के रूप में बुलाया जा सकता है y = z + sqrt(x)). प्रक्रिया कॉल या तो वाक्यात्मक रूप से कथन (कंप्यूटर विज्ञान) के रूप में व्यवहार करते हैं (उदाहरण के लिए, a print प्रक्रिया को कहा जा सकता है if x > 0 then print(x) या जैसे किसी कथन द्वारा स्पष्ट रूप से आह्वान किया जाता है CALL या GOSUB (जैसे, call print(x)). अन्य भाषाएँ, जैसे C (प्रोग्रामिंग भाषा) और लिस्प (प्रोग्रामिंग भाषा), फ़ंक्शन और सबरूटीन के बीच अंतर नहीं करती हैं।

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

C (प्रोग्रामिंग भाषा), C++, और C शार्प (प्रोग्रामिंग भाषा)|C# जैसी प्रोग्रामिंग भाषाओं में, वे फ़ंक्शन जो कोई मान लौटाते हैं और वे फ़ंक्शन जो कोई मान नहीं लौटाते हैं, दोनों को फ़ंक्शन कहा जाता है (गणितीय फ़ंक्शन या कार्यात्मक प्रोग्रामिंग के साथ भ्रमित न हों, जो अलग-अलग अवधारणाएं हैं)।

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

फायदे

किसी प्रोग्राम को फ़ंक्शंस में तोड़ने के फ़ायदों में शामिल हैं:

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

नुकसान

इन-लाइन कोड का उपयोग करने की तुलना में, किसी फ़ंक्शन को लागू करने से कॉल तंत्र में कुछ कम्प्यूटेशनल ओवरहेड लगाया जाता है।[citation needed]

किसी फ़ंक्शन को आम तौर पर मानक हाउसकीपिंग (कंप्यूटिंग) कोड की आवश्यकता होती है - फ़ंक्शन में प्रवेश और निकास दोनों पर (फ़ंक्शन प्रस्तावना - आमतौर पर सामान्य प्रयोजन रजिस्टरों और वापसी पते को न्यूनतम के रूप में सहेजना)।

इतिहास

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

सबरूटीन्स को 1945 में कोनराड ज़ूस के Z4 (कंप्यूटर) में लागू किया गया था।

1945 में, एलन एम. ट्यूरिंग ने कॉल करने और सबरूटीन्स से लौटने के साधन के रूप में बरी और अनबरी शब्दों का इस्तेमाल किया।[11][12]

जनवरी 1947 में जॉन मौचली ने 'बड़े पैमाने पर डिजिटल गणना मशीनरी के एक संगोष्ठी' में सामान्य नोट्स प्रस्तुत किए। हार्वर्ड विश्वविद्यालय और आयुध ब्यूरो, संयुक्त राज्य अमेरिका नौसेना के संयुक्त प्रायोजन के तहत। यहां उन्होंने सीरियल और समानांतर संचालन के सुझाव पर चर्चा की

...the structure of the machine need not be complicated one bit. It is possible, since all the logical characteristics essential to this procedure are available, to evolve a coding instruction for placing the subroutines in the memory at places known to the machine, and in such a way that they may easily be called into use.

In other words, one can designate subroutine A as division and subroutine B as complex multiplication and subroutine C as the evaluation of a standard error of a sequence of numbers, and so on through the list of subroutines needed for a particular problem. ... All these subroutines will then be stored in the machine, and all one needs to do is make a brief reference to them by number, as they are indicated in the coding.[3]

कैथलीन एंटोनेली ने ENIAC टीम में जॉन मौचली के साथ मिलकर काम किया था और ENIAC कंप्यूटर के लिए सबरूटीन्स के लिए एक विचार विकसित किया था जिसे वह द्वितीय विश्व युद्ध के दौरान प्रोग्रामिंग कर रही थी।[13] उसने और अन्य ENIAC प्रोग्रामर्स ने मिसाइल प्रक्षेप पथ की गणना में मदद के लिए सबरूटीन्स का उपयोग किया।[13]

हरमन गोल्डस्टाइन और जॉन वॉन न्यूमैन ने 16 अगस्त 1948 को सबरूटीन्स के उपयोग पर चर्चा करते हुए एक पेपर लिखा था।[14]

कुछ बहुत शुरुआती कंप्यूटर और माइक्रोप्रोसेसर, जैसे कि IBM 1620, Intel 4004 और Intel 8008, और पीआईसी माइक्रोकंट्रोलर, में एकल-निर्देश सबरूटीन कॉल होता है जो रिटर्न पते को संग्रहीत करने के लिए एक समर्पित हार्डवेयर स्टैक का उपयोग करता है - ऐसे हार्डवेयर केवल कुछ स्तरों का समर्थन करते हैं सबरूटीन नेस्टिंग का, लेकिन पुनरावर्ती सबरूटीन का समर्थन कर सकता है। 1960 के दशक के मध्य से पहले की मशीनें - जैसे कि UNIVAC I, PDP-1, और IBM 1130 - आम तौर पर एक कॉलिंग कन्वेंशन का उपयोग करती हैं जो निर्देश काउंटर को सबरूटीन के पहले मेमोरी स्थान में सहेजती है। यह सबरूटीन नेस्टिंग के मनमाने ढंग से गहरे स्तर की अनुमति देता है लेकिन पुनरावर्ती सबरूटीन का समर्थन नहीं करता है। आईबीएम सिस्टम/360 में एक सबरूटीन कॉल निर्देश था जो सहेजे गए निर्देश काउंटर मान को एक सामान्य प्रयोजन रजिस्टर में रखता था; इसका उपयोग मनमाने ढंग से गहरे सबरूटीन नेस्टिंग और पुनरावर्ती सबरूटीन का समर्थन करने के लिए किया जा सकता है। [[पीडीपी-11]] (1970) स्टैक-पुशिंग सबरूटीन कॉल निर्देश वाले पहले कंप्यूटरों में से एक है; यह सुविधा मनमाने ढंग से गहरे सबरूटीन नेस्टिंग और पुनरावर्ती सबरूटीन दोनों का भी समर्थन करती है।[15]

भाषा समर्थन

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

उपयोगकर्ता-लिखित सबरूटीन्स और फ़ंक्शंस का समर्थन करने वाली पहली प्रोग्रामिंग भाषाओं में से एक फ़ोरट्रान#FORTRAN II थी। IBM FORTRAN II कंपाइलर 1958 में जारी किया गया था। ALGOL 58 और अन्य प्रारंभिक प्रोग्रामिंग भाषाओं ने भी प्रक्रियात्मक प्रोग्रामिंग का समर्थन किया।

पुस्तकालय

इस बोझिल दृष्टिकोण के साथ भी, सबरूटीन्स बहुत उपयोगी साबित हुए। उन्होंने कई अलग-अलग कार्यक्रमों में एक ही कोड के उपयोग की अनुमति दी। प्रारंभिक कंप्यूटरों पर मेमोरी एक बहुत ही दुर्लभ संसाधन थी, और सबरूटीन्स ने प्रोग्राम के आकार में महत्वपूर्ण बचत की अनुमति दी थी।

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

अप्रत्यक्ष छलांग द्वारा वापसी

स्व-संशोधित कोड की आवश्यकता को दूर करने के लिए, कंप्यूटर डिजाइनरों ने अंततः एक अप्रत्यक्ष शाखा निर्देश प्रदान किया, जिसका ऑपरेंड, रिटर्न स्टेटमेंट होने के बजाय, रिटर्न एड्रेस वाले एक वेरिएबल या प्रोसेसर रजिस्टर का स्थान था।

उन कंप्यूटरों पर, फ़ंक्शन के रिटर्न जंप को संशोधित करने के बजाय, कॉलिंग प्रोग्राम रिटर्न एड्रेस को एक वेरिएबल में संग्रहीत करेगा ताकि जब फ़ंक्शन पूरा हो जाए, तो यह एक अप्रत्यक्ष जंप निष्पादित करेगा जो पूर्वनिर्धारित वेरिएबल द्वारा दिए गए स्थान पर निष्पादन को निर्देशित करेगा।

सबरूटीन पर जाएं

एक और प्रगति सबरूटीन निर्देश पर छलांग थी, जिसने कॉलिंग जंप के साथ रिटर्न एड्रेस की बचत को जोड़ दिया, जिससे कम्प्यूटेशनल ओवरहेड को काफी कम कर दिया गया।

उदाहरण के लिए, आईबीएम सिस्टम/360 में, प्रक्रिया कॉलिंग के लिए डिज़ाइन किए गए शाखा निर्देश बीएएल या बीएएलआर, कन्वेंशन रजिस्टर 14 द्वारा निर्देश में निर्दिष्ट प्रोसेसर रजिस्टर में रिटर्न एड्रेस को सेव करेंगे। वापस लौटने के लिए, सबरूटीन को केवल निष्पादित करना होगा उस रजिस्टर के माध्यम से एक अप्रत्यक्ष शाखा निर्देश (बीआर)। यदि सबरूटीन को किसी अन्य उद्देश्य के लिए उस रजिस्टर की आवश्यकता होती है (जैसे कि किसी अन्य सबरूटीन को कॉल करना), तो यह रजिस्टर की सामग्री को एक निजी मेमोरी स्थान या रजिस्टर स्टैक (डेटा संरचना) में सहेज लेगा।

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

...
JSB MYSUB    (Calls subroutine MYSUB.)
BB    ...          (Will return here after MYSUB is done.)

मुख्य प्रोग्राम से MYSUB नामक सबरूटीन को कॉल करने के लिए। सबरूटीन को इस प्रकार कोडित किया जाएगा

MYSUB NOP          (Storage for MYSUB's return address.)
AA    ...          (Start of MYSUB's body.)
...
JMP MYSUB,I  (Returns to the calling program.)

JSB निर्देश ने NEXT निर्देश (अर्थात्, BB) के पते को उसके ऑपरेंड (अर्थात्, MYSUB) के रूप में निर्दिष्ट स्थान पर रखा, और फिर उसके बाद अगले स्थान (अर्थात्, AA = MYSUB + 1) पर शाखा दी। सबरूटीन अप्रत्यक्ष जंप JMP MYSUB, I को क्रियान्वित करके मुख्य कार्यक्रम में वापस आ सकता है, जो स्थान MYSUB पर संग्रहीत स्थान पर शाखाबद्ध होता है।

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

संयोग से, एक स्प्रेडशीट में पुनर्गणना निर्भरता की खोज के लिए, 1980 के दशक की शुरुआत में लोटस 1-2-3 द्वारा एक समान विधि का उपयोग किया गया था। अर्थात्, रिटर्न एड्रेस को संग्रहीत करने के लिए प्रत्येक सेल में एक स्थान आरक्षित किया गया था। चूंकि प्राकृतिक पुनर्गणना क्रम के लिए परिपत्र संदर्भों की अनुमति नहीं है, यह मेमोरी में स्टैक के लिए जगह आरक्षित किए बिना ट्री वॉक की अनुमति देता है, जो कि आईबीएम पीसी जैसे छोटे कंप्यूटरों पर बहुत सीमित था।

कॉल स्टैक

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

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

कॉल स्टैक को आमतौर पर मेमोरी के सन्निहित क्षेत्र के रूप में कार्यान्वित किया जाता है। यह एक मनमाना डिज़ाइन विकल्प है कि क्या स्टैक का निचला भाग इस क्षेत्र के भीतर सबसे निचला या उच्चतम पता है, ताकि स्टैक मेमोरी में आगे या पीछे की ओर बढ़ सके; हालाँकि, कई आर्किटेक्चर ने बाद वाले को चुना।[citation needed]

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

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

हालाँकि, कॉल स्टैक विधि का एक और फायदा यह है कि यह रिकर्सन (कंप्यूटर विज्ञान) की अनुमति देता है, क्योंकि एक ही प्रक्रिया में प्रत्येक नेस्टेड कॉल को उसके निजी डेटा का एक अलग उदाहरण मिलता है।

एक थ्रेड (कंप्यूटर विज्ञान)|बहु-थ्रेडेड वातावरण में, आम तौर पर एक से अधिक स्टैक होते हैं।[17] एक ऐसा वातावरण जो पूरी तरह से coroutine या आलसी मूल्यांकन का समर्थन करता है, अपने सक्रियण रिकॉर्ड को संग्रहीत करने के लिए स्टैक के अलावा अन्य डेटा संरचनाओं का उपयोग कर सकता है।

विलंबित स्टैकिंग

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

यह ओवरहेड लीफ प्रक्रियाओं या लीफ फ़ंक्शंस में सबसे स्पष्ट और आपत्तिजनक है, जो बिना किसी प्रक्रिया को कॉल किए वापस लौट आते हैं।[18][19][20] उस ओवरहेड को कम करने के लिए, कई आधुनिक कंपाइलर कॉल स्टैक के उपयोग में तब तक देरी करने का प्रयास करते हैं जब तक कि इसकी वास्तव में आवश्यकता न हो।[citation needed] उदाहरण के लिए, एक प्रक्रिया पी की कॉल कुछ प्रोसेसर रजिस्टरों में कॉल की गई प्रक्रिया के रिटर्न पते और मापदंडों को संग्रहीत कर सकती है, और एक साधारण छलांग द्वारा प्रक्रिया के मुख्य भाग पर नियंत्रण स्थानांतरित कर सकती है। यदि प्रक्रिया P कोई अन्य कॉल किए बिना वापस आती है, तो कॉल स्टैक का उपयोग बिल्कुल नहीं किया जाता है। यदि P को किसी अन्य प्रक्रिया Q को कॉल करने की आवश्यकता है, तो यह किसी भी रजिस्टर (जैसे रिटर्न एड्रेस) की सामग्री को सहेजने के लिए कॉल स्टैक का उपयोग करेगा, जिसकी Q रिटर्न के बाद आवश्यकता होगी।

उदाहरण

सी और सी++

सी (प्रोग्रामिंग भाषा) और सी++ प्रोग्रामिंग भाषाओं में, उपप्रोग्राम को फ़ंक्शंस कहा जाता है (किसी क्लास (कंप्यूटर प्रोग्रामिंग), या फ्री फ़ंक्शंस से जुड़े होने पर इसे सदस्य फ़ंक्शंस के रूप में वर्गीकृत किया जाता है)[21] कब नहीं)। ये भाषाएँ विशेष कीवर्ड का उपयोग करती हैं void यह इंगित करने के लिए कि कोई फ़ंक्शन कोई मान नहीं लौटाता है। ध्यान दें कि C/C++ फ़ंक्शंस के दुष्प्रभाव हो सकते हैं, जिसमें किसी भी वेरिएबल को संशोधित करना भी शामिल है जिनके पते पैरामीटर के रूप में पारित किए गए हैं। उदाहरण:

void Function1() { /* some code */ }

फ़ंक्शन कोई मान नहीं लौटाता है और इसे स्टैंड-अलोन फ़ंक्शन के रूप में कॉल करना पड़ता है, उदाहरण के लिए, Function1();

int Function2() {
  return 5;
}

यह फ़ंक्शन एक परिणाम (संख्या 5) देता है, और कॉल एक अभिव्यक्ति का हिस्सा हो सकता है, उदाहरण के लिए, x + Function2()

char Function3(int number) {
  char selection[] = {'S', 'M', 'T', 'W', 'T', 'F', 'S'};
  return selection[number];
}

यह फ़ंक्शन 0 और 6 के बीच की संख्या को सप्ताह के संबंधित दिन के प्रारंभिक अक्षर में परिवर्तित करता है, अर्थात् 0 से 'S', 1 से 'M', ..., 6 से 'S'। इसे कॉल करने का परिणाम एक वेरिएबल को सौंपा जा सकता है, उदाहरण के लिए, num_day = Function3(number);.

void Function4(int* pointer_to_var) {
  (*pointer_to_var)++;
}

यह फ़ंक्शन कोई मान नहीं लौटाता है बल्कि उस वेरिएबल को संशोधित करता है जिसका पता पैरामीटर के रूप में पारित किया गया है; इसे साथ बुलाया जाएगा Function4(&variable_to_increment);.

बुनियादी बोलियाँ

माइक्रोसॉफ्ट स्मॉल बेसिक

Example()                               ' Calls the subroutine

Sub Example                             ' Begins the subroutine
    TextWindow.WriteLine("This is an example of a subroutine in Microsoft Small Basic.")  ' What the subroutine does
EndSub                                  ' Ends the subroutine

उपरोक्त उदाहरण में, Example() सबरूटीन को कॉल करता है।[22] वास्तविक सबरूटीन को परिभाषित करने के लिए, Sub सबरूटीन नाम के साथ कीवर्ड का उपयोग किया जाना चाहिए Sub. सामग्री का अनुसरण करने के बाद, EndSub टाइप करना होगा.

विज़ुअल बेसिक (क्लासिक)

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

  • 'वैल्यू द्वारा [बायवैल]' - एड्रेस को पास करने के बजाय, वैल्यू की एक कॉपी पास करके किसी तर्क के मान को प्रक्रिया में पास करने का एक तरीका। परिणामस्वरूप, वेरिएबल का वास्तविक मान उस प्रक्रिया द्वारा नहीं बदला जा सकता है जिसके लिए इसे पारित किया गया है।
  • 'संदर्भ द्वारा [ByRef]' - किसी तर्क के मान की एक प्रति पास करने के बजाय, वेरिएबल का एक पता पास करके किसी प्रक्रिया में उसके मान को पास करने का एक तरीका। यह प्रक्रिया को वास्तविक चर तक पहुंचने की अनुमति देता है। परिणामस्वरूप, वेरिएबल का वास्तविक मान उस प्रक्रिया द्वारा बदला जा सकता है जिसके लिए इसे पारित किया गया है। जब तक अन्यथा निर्दिष्ट न हो, तर्क संदर्भ द्वारा पारित किए जाते हैं।
  • 'सार्वजनिक' (वैकल्पिक) - इंगित करता है कि फ़ंक्शन प्रक्रिया सभी मॉड्यूल में अन्य सभी प्रक्रियाओं के लिए पहुंच योग्य है। यदि ऐसे मॉड्यूल में उपयोग किया जाता है जिसमें विकल्प निजी है, तो प्रक्रिया परियोजना के बाहर उपलब्ध नहीं है।
  • 'निजी' (वैकल्पिक) - इंगित करता है कि फ़ंक्शन प्रक्रिया केवल उस मॉड्यूल में अन्य प्रक्रियाओं के लिए पहुंच योग्य है जहां इसे घोषित किया गया है।
  • 'मित्र' (वैकल्पिक) - केवल क्लास मॉड्यूल में उपयोग किया जाता है। इंगित करता है कि फ़ंक्शन प्रक्रिया पूरे प्रोजेक्ट में दिखाई देती है, लेकिन किसी ऑब्जेक्ट के उदाहरण के नियंत्रक को दिखाई नहीं देती है।
Private Function Function1()
    ' Some Code Here
End Function

फ़ंक्शन कोई मान नहीं लौटाता है और इसे स्टैंड-अलोन फ़ंक्शन के रूप में कॉल करना पड़ता है, उदाहरण के लिए, Function1

Private Function Function2() as Integer
    Function2 = 5
End Function

यह फ़ंक्शन एक परिणाम (संख्या 5) देता है, और कॉल एक अभिव्यक्ति का हिस्सा हो सकता है, उदाहरण के लिए, x + Function2()

Private Function Function3(ByVal intValue as Integer) as String
    Dim strArray(6) as String
    strArray = Array("M", "T", "W", "T", "F", "S", "S")
    Function3 = strArray(intValue)
End Function

यह फ़ंक्शन 0 और 6 के बीच की संख्या को सप्ताह के संबंधित दिन के प्रारंभिक अक्षर में परिवर्तित करता है, अर्थात् 0 से 'M', 1 से 'T', ..., 6 से 'S'। इसे कॉल करने का परिणाम एक वेरिएबल को सौंपा जा सकता है, उदाहरण के लिए, num_day = Function3(number).

Private Function Function4(ByRef intValue as Integer)
    intValue = intValue + 1
End Function

यह फ़ंक्शन कोई मान नहीं लौटाता है बल्कि उस वेरिएबल को संशोधित करता है जिसका पता पैरामीटर के रूप में पारित किया गया है; इसे साथ बुलाया जाएगाFunction4(variable_to_increment).

पीएल/आई

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

<पूर्व>

परिवर्तन_चिह्न: प्रक्रिया(सरणी);

 सरणी घोषित करें(*,*) फ़्लोट;
 सरणी = -सरणी;

अंत परिवर्तन_चिह्न;

</पूर्व>

इसे विभिन्न सरणियों के साथ निम्नानुसार कहा जा सकता है:

<पूर्व>

/* पहली सरणी सीमा -5 से +10 और 3 से 9 तक */

array1 घोषित करें (-5:10, 3:9)फ्लोट;

/* दूसरी सरणी की सीमाएं 1 से 16 और 1 से 16 तक */

सारणी 2 (16,16) फ्लोट घोषित करें;

कॉल परिवर्तन_चिह्न(सरणी1);

कॉल Change_sign(array2);

</पूर्व>

पायथन

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

def simple_function():
    print('Hello world!')
    print('Wikipedia')
simple_function()
# output will be:
Hello World!
Wikipedia
                  

def func(name)
    print("welcome "+name)
print(func("martin"))
#output will be: welcome martin


स्थानीय चर, पुनरावर्तन और पुनर्प्रवेश

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

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

int Fib(int n) {
  if (n <= 1) {
    return n;
  }
  return Fib(n - 1) + Fib(n - 2);
}

फोरट्रान जैसी शुरुआती भाषाओं ने शुरू में रिकर्सन का समर्थन नहीं किया क्योंकि चर को सांख्यिकीय रूप से आवंटित किया गया था, साथ ही रिटर्न पते के लिए स्थान भी।[24] प्रारंभिक कंप्यूटर अनुदेश सेटों ने रिटर्न पते और वेरिएबल्स को स्टैक पर संग्रहीत करना कठिन बना दिया था। सूचकांक रजिस्टर या सामान्य प्रयोजन रजिस्टर वाली मशीनें, जैसे, सीडीसी 6000 श्रृंखला, पीडीपी-6, जीई 635, सिस्टम/360, यूनिवैक 1100 श्रृंखला, उन रजिस्टरों में से एक को स्टेक सूचक के रूप में उपयोग कर सकती हैं।

ALGOL के बाद की आधुनिक भाषाएँ जैसे PL/I और C (प्रोग्रामिंग भाषा) लगभग हमेशा एक स्टैक का उपयोग करती हैं, जो आमतौर पर उपप्रोग्राम के प्रत्येक निष्पादन के लिए एक नया सक्रियण रिकॉर्ड प्रदान करने के लिए अधिकांश आधुनिक कंप्यूटर निर्देश सेट द्वारा समर्थित होती है। इस तरह, नेस्टेड निष्पादन प्रगति में अन्य निलंबित निष्पादनों पर प्रभाव की चिंता किए बिना अपने स्थानीय चर को संशोधित करने के लिए स्वतंत्र है। जैसे ही नेस्टेड कॉल जमा होती हैं, एक कॉल स्टैक संरचना बनती है, जिसमें प्रत्येक निलंबित उपप्रोग्राम के लिए एक सक्रियण रिकॉर्ड होता है। वास्तव में, यह स्टैक संरचना वस्तुतः सर्वव्यापी है, और इसलिए सक्रियण रिकॉर्ड को आमतौर पर स्टैक फ़्रेम कहा जाता है।

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

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

ओवरलोडिंग

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

ऑब्जेक्ट-ओरिएंटेड प्रोग्रामिंग में, जब एक ही नाम वाले फ़ंक्शंस की एक श्रृंखला विभिन्न पैरामीटर प्रोफाइल या विभिन्न प्रकार के पैरामीटर स्वीकार कर सकती है, तो प्रत्येक फ़ंक्शन को विधि अतिभार कहा जाता है।

यहां C++ में फ़ंक्शन ओवरलोडिंग का एक उदाहरण दिया गया है, जो एक ही नाम (क्षेत्र) लेकिन विभिन्न मापदंडों के साथ दो कार्यों के कार्यान्वयन को प्रदर्शित करता है:

#include <iostream>

double Area(double h, double w) { return h * w; } 
/* The first Area function is for finding the area of a rectangle, 
 * so it accepts two numbers as parameters, for the height and width. */

double Area(double r) { return r * r * 3.14; }
/* The second Area function is for finding the area of a circle,
 * so it only accepts one number as a parameter, for the radius. */

int main() {
  double rectangle_area = Area(3, 4); // This calls the first Area function, because two parameters are provided.
  double circle_area = Area(5);       // This calls the second Area function, because only one parameter is provided.

  std::cout << "Area of a rectangle is " << rectangle_area << std::endl;
  std::cout << "Area of a circle is " << circle_area << std::endl;
}

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

पीएल/आई के पास है GENERIC विभिन्न प्रकार के तर्कों के साथ बुलाए गए प्रविष्टि संदर्भों के एक सेट के लिए एक सामान्य नाम परिभाषित करने की विशेषता। उदाहरण: <पूर्व> जेनरिक नाम घोषित करें(

                   नाम कब(फिक्स्ड बाइनरी),
                   लौ जब(तैरना),
                   पथनाम अन्यथा

);

प्रत्येक प्रविष्टि के लिए एकाधिक तर्क परिभाषाएँ निर्दिष्ट की जा सकती हैं। जब तर्क फिक्स्ड बाइनरी हो तो gen_name पर कॉल करने पर नाम पर कॉल आएगी, FLOAT होने पर फ्लेम आदि पर कॉल आएगी। यदि तर्क किसी भी विकल्प से मेल नहीं खाता है तो पथनाम पर कॉल नहीं किया जाएगा।

बंद

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

सम्मेलन

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

कुछ प्रोग्रामर सुझाव देते हैं कि एक फ़ंक्शन को केवल एक ही कार्य करना चाहिए, और यदि कोई फ़ंक्शन एक से अधिक कार्य करता है, तो उसे अधिक कार्यों में विभाजित किया जाना चाहिए। उनका तर्क है कि सॉफ़्टवेयर रखरखाव में फ़ंक्शंस प्रमुख घटक हैं, और प्रोग्राम में उनकी भूमिकाएँ अलग रहनी चाहिए।

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

वापसी कोड

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

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

           BAL  14, SUBRTN01    go to a subroutine, storing return address in R14
           B    TABLE(15)      use returned value in reg 15 to index the branch table,
*                              branching to the appropriate branch instr.
TABLE      B    OK             return code =00   GOOD                  }
           B    BAD            return code =04   Invalid input         } Branch table
           B    ERROR          return code =08   Unexpected condition  }


फ़ंक्शन कॉल का अनुकूलन

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

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

इनलाइनिंग

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

यह भी देखें

संदर्भ

  1. U.S. Election Assistance Commission (2007). "Definitions of Words with Special Meanings". Voluntary Voting System Guidelines. Archived from the original on 2012-12-08. Retrieved 2013-01-14.
  2. Subrata Dasgupta (7 January 2014). It Began with Babbage: The Genesis of Computer Science. Oxford University Press. pp. 155–. ISBN 978-0-19-930943-6.
  3. 3.0 3.1 Mauchly, J.W. (1982). "Preparation of Problems for EDVAC-type Machines". In Randell, Brian (ed.). डिजिटल कंप्यूटर की उत्पत्ति. Springer. pp. 393–397. doi:10.1007/978-3-642-61812-3_31. ISBN 978-3-642-61814-7.
  4. Wheeler, D. J. (1952). "The use of sub-routines in programmes" (PDF). Proceedings of the 1952 ACM national meeting (Pittsburgh) on - ACM '52. p. 235. doi:10.1145/609784.609816.
  5. Wilkes, M. V.; Wheeler, D. J.; Gill, S. (1951). इलेक्ट्रॉनिक डिजिटल कंप्यूटर के लिए प्रोग्राम तैयार करना. Addison-Wesley.
  6. Dainith, John (2004). ""सबरूटीन खोलें।" कंप्यूटिंग का एक शब्दकोश". Encyclopedia.com. Retrieved January 14, 2013.
  7. Turing, Alan M. (1945), Report by Dr. A.M. Turing on proposals for the development of an Automatic Computing Engine (ACE): Submitted to the Executive Committee of the NPL in February 1946 reprinted in Copeland, B. J., ed. (2005). Alan Turing's Automatic Computing Engine. Oxford: Oxford University Press. p. 383. ISBN 0-19-856593-3.
  8. Donald E. Knuth (1997). The Art of Computer Programming, Volume I: Fundamental Algorithms. Addison-Wesley. ISBN 0-201-89683-4.
  9. O.-J. Dahl; E. W. Dijkstra; C. A. R. Hoare (1972). संरचित प्रोग्रामिंग. Academic Press. ISBN 0-12-200550-3.
  10. Wilson, Leslie B. (2001). तुलनात्मक प्रोग्रामिंग भाषाएँ, तीसरा संस्करण. Addison-Wesley. p. 140. ISBN 0-201-71012-9.
  11. Turing, Alan Mathison (1946-03-19) [1945], Proposals for Development in the Mathematics Division of an Automatic Computing Engine (ACE) (एनबी। 1946-03-19 को राष्ट्रीय भौतिक प्रयोगशाला (ग्रेट ब्रिटेन) की कार्यकारी समिति के समक्ष प्रस्तुत किया गया।)
  12. Carpenter, Brian Edward; Doran, Robert William (1977-01-01) [October 1975]. "दूसरी ट्यूरिंग मशीन". The Computer Journal. 20 (3): 269–279. doi:10.1093/comjnl/20.3.269. (11 पृष्ठ)
  13. 13.0 13.1 Isaacson, Walter (18 September 2014). "ENIAC की महिलाओं पर वाल्टर इसाकसन". Fortune (in English). Archived from the original on 12 December 2018. Retrieved 2018-12-14.
  14. Planning and Coding of Problems for an Electronic Computing Instrument, Pt 2, Vol. 3 https://library.ias.edu/files/pdfs/ecp/planningcodingof0103inst.pdf Archived 12 November 2018 at the Wayback Machine (see pg 163 of the pdf for the relevant page)
  15. Guy Lewis Steele Jr. AI Memo 443. 'Debunking the "Expensive Procedure Call" Myth; or, Procedure call implementations considered harmful". Section "C. Why Procedure Calls Have a Bad Reputation".
  16. Frank, Thomas S. (1983). Introduction to the PDP-11 and Its Assembly Language. Prentice-Hall software series. Prentice-Hall. p. 195. ISBN 9780134917047. Retrieved 2016-07-06. We could supply our assembling clerk with copies of the source code for all of our useful subroutines and then when presenting him with a mainline program for assembly, tell him which subroutines will be called in the mainline [...]
  17. Buttlar, Dick; Farrell, Jacqueline; Nichols, Bradford (1996). PThreads Programming: A POSIX Standard for Better Multiprocessing. "O'Reilly Media, Inc.". pp. 2–5. ISBN 978-1-4493-6475-5. OCLC 1036778036.
  18. "एआरएम सूचना केंद्र". Infocenter.arm.com. Retrieved 2013-09-29.
  19. "x64 stack usage". Microsoft Docs. Microsoft. Retrieved 5 August 2019.
  20. "फ़ंक्शन प्रकार". Msdn.microsoft.com. Retrieved 2013-09-29.
  21. "निःशुल्क फ़ंक्शन से क्या तात्पर्य है".
  22. "Small Basic Getting Started Guide: Chapter 9: Subroutines". Microsoft.
  23. "4. More Control Flow Tools — Python 3.9.7 documentation".
  24. Verhoeff, Tom (2018). "A Master Class on Recursion". In Böckenhauer, Hans-Joachim; Komm, Dennis; Unger, Walter (eds.). निचली सीमा और उच्च ऊंचाई के बीच रोमांच: जुराज ह्रोमकोविच को उनके 60वें जन्मदिन के अवसर पर समर्पित निबंध. Springer. p. 616. ISBN 978-3-319-98355-4. OCLC 1050567095.