अनाम पुनरावर्तन: Difference between revisions
(Created page with "{{short description|Recursion without calling a function by name}} कंप्यूटर विज्ञान में, अनाम रिकर्सन रिक...") |
No edit summary |
||
Line 1: | Line 1: | ||
{{short description|Recursion without calling a function by name}} | {{short description|Recursion without calling a function by name}} | ||
[[कंप्यूटर विज्ञान]] में, अनाम रिकर्सन [[रिकर्सन (कंप्यूटर विज्ञान)]] है जो स्पष्ट रूप से किसी फ़ंक्शन को नाम से नहीं बुलाता है। यह या तो स्पष्ट रूप से, उच्च-क्रम वाले फ़ंक्शन का उपयोग करके किया जा सकता है - किसी फ़ंक्शन को | [[कंप्यूटर विज्ञान]] में, अनाम रिकर्सन [[रिकर्सन (कंप्यूटर विज्ञान)]] है जो स्पष्ट रूप से किसी फ़ंक्शन को नाम से नहीं बुलाता है। यह या तो स्पष्ट रूप से, उच्च-क्रम वाले फ़ंक्शन का उपयोग करके किया जा सकता है - किसी फ़ंक्शन को तर्क के रूप में पारित करना और उसे कॉल करना - या परोक्ष रूप से, [[प्रतिबिंब (कंप्यूटर प्रोग्रामिंग)]] सुविधाओं के माध्यम से जो किसी को वर्तमान संदर्भ, विशेष रूप से वर्तमान फ़ंक्शन या कभी-कभी वर्तमान फ़ंक्शन के कॉलिंग फ़ंक्शन के आधार पर कुछ कार्यों तक पहुंचने की अनुमति देता है। | ||
प्रोग्रामिंग अभ्यास में, [[जावास्क्रिप्ट]] में अनाम रिकर्सन का विशेष रूप से उपयोग किया जाता है, जो इसका समर्थन करने के लिए प्रतिबिंब सुविधाएं प्रदान करता है। हालाँकि, सामान्य प्रोग्रामिंग अभ्यास में, इसे खराब शैली माना जाता है, और इसके बजाय नामित कार्यों के साथ रिकर्सन का सुझाव दिया जाता है। कार्यों को तर्कों के रूप में स्पष्ट रूप से पारित करने के माध्यम से अज्ञात पुनरावृत्ति किसी भी भाषा में संभव है जो तर्कों के रूप में कार्यों का समर्थन करती है, हालांकि व्यवहार में इसका उपयोग शायद ही कभी किया जाता है, क्योंकि यह नाम से स्पष्ट रूप से पुनरावृत्ति की तुलना में अधिक लंबा और कम स्पष्ट है। | प्रोग्रामिंग अभ्यास में, [[जावास्क्रिप्ट]] में अनाम रिकर्सन का विशेष रूप से उपयोग किया जाता है, जो इसका समर्थन करने के लिए प्रतिबिंब सुविधाएं प्रदान करता है। हालाँकि, सामान्य प्रोग्रामिंग अभ्यास में, इसे खराब शैली माना जाता है, और इसके बजाय नामित कार्यों के साथ रिकर्सन का सुझाव दिया जाता है। कार्यों को तर्कों के रूप में स्पष्ट रूप से पारित करने के माध्यम से अज्ञात पुनरावृत्ति किसी भी भाषा में संभव है जो तर्कों के रूप में कार्यों का समर्थन करती है, हालांकि व्यवहार में इसका उपयोग शायद ही कभी किया जाता है, क्योंकि यह नाम से स्पष्ट रूप से पुनरावृत्ति की तुलना में अधिक लंबा और कम स्पष्ट है। | ||
Line 9: | Line 9: | ||
अनाम रिकर्सन का उपयोग मुख्य रूप से अज्ञात कार्यों के लिए रिकर्सन की अनुमति देने में किया जाता है, खासकर जब वे क्लोजर (कंप्यूटर विज्ञान) बनाते हैं या फ़ंक्शन के [[नाम बंधन]] से बचने के लिए [[कॉलबैक (कंप्यूटर प्रोग्रामिंग)]] के रूप में उपयोग किए जाते हैं। | अनाम रिकर्सन का उपयोग मुख्य रूप से अज्ञात कार्यों के लिए रिकर्सन की अनुमति देने में किया जाता है, खासकर जब वे क्लोजर (कंप्यूटर विज्ञान) बनाते हैं या फ़ंक्शन के [[नाम बंधन]] से बचने के लिए [[कॉलबैक (कंप्यूटर प्रोग्रामिंग)]] के रूप में उपयोग किए जाते हैं। | ||
अनाम रिकर्सन में मुख्य रूप से वर्तमान फ़ंक्शन को कॉल करना शामिल है, जिसके परिणामस्वरूप प्रत्यक्ष रिकर्सन होता है। अनाम अप्रत्यक्ष रिकर्सन संभव है, जैसे कि कॉलर (पिछले फ़ंक्शन) को कॉल करके, या, शायद ही कभी, [[कॉल स्टैक]] में और ऊपर जाकर, और इसे पारस्परिक रिकर्सन उत्पन्न करने के लिए श्रृंखलाबद्ध किया जा सकता है। वर्तमान फ़ंक्शन का स्व-संदर्भ [[ ऑब्जेक्ट ओरिएंटेड प्रोग्रामिंग ]] में इस (कंप्यूटर प्रोग्रामिंग) कीवर्ड का | अनाम रिकर्सन में मुख्य रूप से वर्तमान फ़ंक्शन को कॉल करना शामिल है, जिसके परिणामस्वरूप प्रत्यक्ष रिकर्सन होता है। अनाम अप्रत्यक्ष रिकर्सन संभव है, जैसे कि कॉलर (पिछले फ़ंक्शन) को कॉल करके, या, शायद ही कभी, [[कॉल स्टैक]] में और ऊपर जाकर, और इसे पारस्परिक रिकर्सन उत्पन्न करने के लिए श्रृंखलाबद्ध किया जा सकता है। वर्तमान फ़ंक्शन का स्व-संदर्भ [[ ऑब्जेक्ट ओरिएंटेड प्रोग्रामिंग |ऑब्जेक्ट ओरिएंटेड प्रोग्रामिंग]] में इस (कंप्यूटर प्रोग्रामिंग) कीवर्ड का कार्यात्मक समकक्ष है, जो किसी को वर्तमान संदर्भ को संदर्भित करने की अनुमति देता है। | ||
अनाम रिकर्सन का उपयोग नामित फ़ंक्शंस के लिए भी किया जा सकता है, बल्कि उन्हें नाम से कॉल करना, यह निर्दिष्ट करना कि कोई वर्तमान फ़ंक्शन पर रिकर्सन कर रहा है, या किसी को उस नाम को बदलने की आवश्यकता के बिना फ़ंक्शन का नाम बदलने की अनुमति देना जहां यह स्वयं कॉल करता है। हालाँकि, [[प्रोग्रामिंग शैली]] के मामले में यह आम तौर पर नहीं किया जाता है। | अनाम रिकर्सन का उपयोग नामित फ़ंक्शंस के लिए भी किया जा सकता है, बल्कि उन्हें नाम से कॉल करना, यह निर्दिष्ट करना कि कोई वर्तमान फ़ंक्शन पर रिकर्सन कर रहा है, या किसी को उस नाम को बदलने की आवश्यकता के बिना फ़ंक्शन का नाम बदलने की अनुमति देना जहां यह स्वयं कॉल करता है। हालाँकि, [[प्रोग्रामिंग शैली]] के मामले में यह आम तौर पर नहीं किया जाता है। | ||
Line 16: | Line 16: | ||
===नामित फ़ंक्शन=== | ===नामित फ़ंक्शन=== | ||
सामान्य विकल्प नामित फ़ंक्शंस और नामित रिकर्सन का उपयोग करना है। | सामान्य विकल्प नामित फ़ंक्शंस और नामित रिकर्सन का उपयोग करना है। अनाम फ़ंक्शन को देखते हुए, यह या तो फ़ंक्शन में नाम बाइंड करके किया जा सकता है, जैसा कि जावास्क्रिप्ट में नामित फ़ंक्शन एक्सप्रेशन में होता है, या फ़ंक्शन को वेरिएबल में निर्दिष्ट करके और फिर वेरिएबल को कॉल करके किया जा सकता है, जैसा कि जावास्क्रिप्ट में फ़ंक्शन स्टेटमेंट में होता है। चूँकि जो भाषाएँ अनाम फ़ंक्शंस की अनुमति देती हैं, वे आम तौर पर इन फ़ंक्शंस को वेरिएबल्स (यदि प्रथम श्रेणी फ़ंक्शंस नहीं) को निर्दिष्ट करने की अनुमति देती हैं, तो कई भाषाएँ स्वयं फ़ंक्शन को संदर्भित करने का कोई तरीका प्रदान नहीं करती हैं, और स्पष्ट रूप से अनाम रिकर्सन को अस्वीकार करती हैं; उदाहरणों में गो (प्रोग्रामिंग भाषा) शामिल है।<ref>[https://code.google.com/p/go/issues/detail?id=226 Issue 226: It's impossible to recurse a anonymous function in Go without workarounds.]</ref> | ||
उदाहरण के लिए, जावास्क्रिप्ट में फैक्टोरियल फ़ंक्शन को अज्ञात रिकर्सन के माध्यम से परिभाषित किया जा सकता है:<ref name=olliej>[https://stackoverflow.com/a/235760 answer] by olliej, Oct 25 '08 to "[https://stackoverflow.com/q/103598 Why was the arguments.callee.caller property deprecated in JavaScript?]", ''StackOverflow''</ref> | उदाहरण के लिए, जावास्क्रिप्ट में फैक्टोरियल फ़ंक्शन को अज्ञात रिकर्सन के माध्यम से परिभाषित किया जा सकता है:<ref name=olliej>[https://stackoverflow.com/a/235760 answer] by olliej, Oct 25 '08 to "[https://stackoverflow.com/q/103598 Why was the arguments.callee.caller property deprecated in JavaScript?]", ''StackOverflow''</ref> | ||
<syntaxhighlight lang="javascript"> | <syntaxhighlight lang="javascript"> | ||
Line 32: | Line 32: | ||
===फ़ंक्शंस को तर्क के रूप में पास करना=== | ===फ़ंक्शंस को तर्क के रूप में पास करना=== | ||
वर्तमान फ़ंक्शन या कॉलिंग फ़ंक्शन को संदर्भित करने के लिए तंत्र के बिना भी, ऐसी भाषा में अज्ञात रिकर्सन संभव है जो फ़ंक्शन को तर्क के रूप में अनुमति देता है। यह मूल पुनरावर्ती फ़ंक्शन में | वर्तमान फ़ंक्शन या कॉलिंग फ़ंक्शन को संदर्भित करने के लिए तंत्र के बिना भी, ऐसी भाषा में अज्ञात रिकर्सन संभव है जो फ़ंक्शन को तर्क के रूप में अनुमति देता है। यह मूल पुनरावर्ती फ़ंक्शन में और पैरामीटर जोड़कर और पुनरावर्ती कॉल के लिए फ़ंक्शन के रूप में इस पैरामीटर का उपयोग करके किया जाता है। यह उच्च-क्रम फ़ंक्शन बनाता है, और इस उच्च फ़ंक्शन को पास करने से वास्तविक पुनरावर्ती फ़ंक्शन के भीतर अज्ञात रिकर्सन की अनुमति मिलती है। इस उच्च क्रम फ़ंक्शन पर निश्चित-बिंदु कॉम्बिनेटर लागू करके इसे पूरी तरह से गुमनाम रूप से किया जा सकता है। यह मुख्य रूप से अकादमिक रुचि का है, विशेष रूप से यह दिखाने के लिए कि लैम्ब्डा कैलकुलस में रिकर्सन है, क्योंकि परिणामी अभिव्यक्ति मूल नामित रिकर्सिव फ़ंक्शन की तुलना में काफी अधिक जटिल है। इसके विपरीत, फिक्स्ड-पॉइंटेड कॉम्बिनेटर्स के उपयोग को सामान्य रूप से अज्ञात रिकर्सन के रूप में संदर्भित किया जा सकता है, क्योंकि यह उनका उल्लेखनीय उपयोग है, हालांकि उनके पास अन्य अनुप्रयोग हैं।<ref>This terminology appear to be largely [[mathematical folklore|folklore]], but it does appear in the following: | ||
* Trey Nash, ''Accelerated C# 2008'', Apress, 2007, {{ISBN|1-59059-873-3}}, p. 462—463. Derived substantially<!--gives him credit!--> from [http://www.linkedin.com/pub/wes-dyer/2/727/a39 Wes Dyer]'s blog (see next item). | * Trey Nash, ''Accelerated C# 2008'', Apress, 2007, {{ISBN|1-59059-873-3}}, p. 462—463. Derived substantially<!--gives him credit!--> from [http://www.linkedin.com/pub/wes-dyer/2/727/a39 Wes Dyer]'s blog (see next item). | ||
* Wes Dyer [http://blogs.msdn.com/wesdyer/archive/2007/02/02/anonymous-recursion-in-c.aspx Anonymous Recursion in C#], February 02, 2007, contains a substantially similar example found in the book above, but accompanied by more discussion.</ref><ref name=ifworks>The If Works [http://blog.jcoglan.com/2008/01/10/deriving-the-y-combinator/ Deriving the Y combinator], January 10th, 2008</ref> | * Wes Dyer [http://blogs.msdn.com/wesdyer/archive/2007/02/02/anonymous-recursion-in-c.aspx Anonymous Recursion in C#], February 02, 2007, contains a substantially similar example found in the book above, but accompanied by more discussion.</ref><ref name=ifworks>The If Works [http://blog.jcoglan.com/2008/01/10/deriving-the-y-combinator/ Deriving the Y combinator], January 10th, 2008</ref> | ||
इसे नीचे पायथन का उपयोग करके दर्शाया गया है। सबसे पहले, रिकर्सन नामक | इसे नीचे पायथन का उपयोग करके दर्शाया गया है। सबसे पहले, रिकर्सन नामक मानक: | ||
<syntaxhighlight lang="python"> | <syntaxhighlight lang="python"> | ||
def fact(n): | def fact(n): | ||
Line 56: | Line 56: | ||
fact = lambda n: fact1(fact1, n) | fact = lambda n: fact1(fact1, n) | ||
</syntaxhighlight> | </syntaxhighlight> | ||
दूसरी पंक्ति को | दूसरी पंक्ति को सामान्य उच्च-क्रम फ़ंक्शन द्वारा प्रतिस्थापित किया जा सकता है जिसे [[संयोजनात्मक तर्क]] कहा जाता है: | ||
<syntaxhighlight lang="python"> | <syntaxhighlight lang="python"> | ||
F = lambda f: (lambda x: f(f, x)) | F = lambda f: (lambda x: f(f, x)) | ||
Line 67: | Line 67: | ||
(lambda g, n1: 1 if n1 == 0 else n1 * g(g, n1 - 1)) | (lambda g, n1: 1 if n1 == 0 else n1 * g(g, n1 - 1)) | ||
</syntaxhighlight> | </syntaxhighlight> | ||
लैम्ब्डा कैलकुलस में, जो केवल | लैम्ब्डा कैलकुलस में, जो केवल ही चर के कार्यों का उपयोग करता है, यह फिक्स्ड-पॉइंट कॉम्बिनेटर के माध्यम से किया जा सकता है। पहले दो वेरिएबल्स के उच्च-क्रम वाले फ़ंक्शन को एकल वेरिएबल का फ़ंक्शन बनाएं, जो [[करी]] द्वारा सीधे फ़ंक्शन लौटाता है: | ||
<syntaxhighlight lang="python"> | <syntaxhighlight lang="python"> | ||
fact1 = lambda f: (lambda n1: 1 if n1 == 0 else n1 * f(f)(n1 - 1)) | fact1 = lambda f: (lambda n1: 1 if n1 == 0 else n1 * f(f)(n1 - 1)) | ||
Line 85: | Line 85: | ||
fact = C(D(fact1)) | fact = C(D(fact1)) | ||
</syntaxhighlight> | </syntaxhighlight> | ||
दो कॉम्बिनेटरों को | दो कॉम्बिनेटरों को में मिलाने से फिक्स्ड-पॉइंट कॉम्बिनेटर प्राप्त होता है: | ||
<syntaxhighlight lang="python"> | <syntaxhighlight lang="python"> | ||
C = lambda x: x(x) | C = lambda x: x(x) | ||
Line 100: | Line 100: | ||
fact = Y(fact1) | fact = Y(fact1) | ||
</syntaxhighlight> | </syntaxhighlight> | ||
इनके संयोजन से लैम्ब्डा कैलकुलस (एकल चर के अज्ञात कार्य) में फैक्टोरियल की | इनके संयोजन से लैम्ब्डा कैलकुलस (एकल चर के अज्ञात कार्य) में फैक्टोरियल की पुनरावर्ती परिभाषा प्राप्त होती है:<ref>[https://stackoverflow.com/a/10144992/2025416 Nux's answer] to "[https://stackoverflow.com/q/481692 Can a lambda function call itself recursively in Python?]"</ref> | ||
<syntaxhighlight lang="python"> | <syntaxhighlight lang="python"> | ||
(lambda f: (lambda x: f(lambda v: x(x)(v))) | (lambda f: (lambda x: f(lambda v: x(x)(v))) | ||
Line 130: | Line 130: | ||
===[[पर्ल]]=== | ===[[पर्ल]]=== | ||
पर्ल 5.16 से शुरू होकर, वर्तमान सबरूटीन इसके माध्यम से पहुंच योग्य है <code>__SUB__</code> टोकन, जो वर्तमान सबरूटीन का संदर्भ लौटाता है, या <code>undef</code> | पर्ल 5.16 से शुरू होकर, वर्तमान सबरूटीन इसके माध्यम से पहुंच योग्य है <code>__SUB__</code> टोकन, जो वर्तमान सबरूटीन का संदर्भ लौटाता है, या <code>undef</code> सबरूटीन के बाहर.<ref>Perldoc, "[http://perldoc.perl.org/feature.html#The-'current_sub'-feature The 'current_sub' feature]", perldoc feature</ref> यह अज्ञात रिकर्सन की अनुमति देता है, जैसे कि फैक्टोरियल के निम्नलिखित कार्यान्वयन में: | ||
<syntaxhighlight lang="perl"> | <syntaxhighlight lang="perl"> | ||
#!/usr/bin/perl | #!/usr/bin/perl |
Revision as of 16:30, 2 August 2023
कंप्यूटर विज्ञान में, अनाम रिकर्सन रिकर्सन (कंप्यूटर विज्ञान) है जो स्पष्ट रूप से किसी फ़ंक्शन को नाम से नहीं बुलाता है। यह या तो स्पष्ट रूप से, उच्च-क्रम वाले फ़ंक्शन का उपयोग करके किया जा सकता है - किसी फ़ंक्शन को तर्क के रूप में पारित करना और उसे कॉल करना - या परोक्ष रूप से, प्रतिबिंब (कंप्यूटर प्रोग्रामिंग) सुविधाओं के माध्यम से जो किसी को वर्तमान संदर्भ, विशेष रूप से वर्तमान फ़ंक्शन या कभी-कभी वर्तमान फ़ंक्शन के कॉलिंग फ़ंक्शन के आधार पर कुछ कार्यों तक पहुंचने की अनुमति देता है।
प्रोग्रामिंग अभ्यास में, जावास्क्रिप्ट में अनाम रिकर्सन का विशेष रूप से उपयोग किया जाता है, जो इसका समर्थन करने के लिए प्रतिबिंब सुविधाएं प्रदान करता है। हालाँकि, सामान्य प्रोग्रामिंग अभ्यास में, इसे खराब शैली माना जाता है, और इसके बजाय नामित कार्यों के साथ रिकर्सन का सुझाव दिया जाता है। कार्यों को तर्कों के रूप में स्पष्ट रूप से पारित करने के माध्यम से अज्ञात पुनरावृत्ति किसी भी भाषा में संभव है जो तर्कों के रूप में कार्यों का समर्थन करती है, हालांकि व्यवहार में इसका उपयोग शायद ही कभी किया जाता है, क्योंकि यह नाम से स्पष्ट रूप से पुनरावृत्ति की तुलना में अधिक लंबा और कम स्पष्ट है।
सैद्धांतिक कंप्यूटर विज्ञान में, अनाम रिकर्सन महत्वपूर्ण है, क्योंकि यह दर्शाता है कि कोई नामित कार्यों की आवश्यकता के बिना रिकर्सन लागू कर सकता है। यह लैम्ब्डा कैलकुलस के लिए विशेष रूप से महत्वपूर्ण है, जिसमें अनाम यूनरी फ़ंक्शन हैं, लेकिन किसी भी पुनरावर्ती फ़ंक्शन की गणना करने में सक्षम है। इस अनाम रिकर्सन को निश्चित-बिंदु कॉम्बिनेटर के माध्यम से सामान्य रूप से उत्पादित किया जा सकता है।
उपयोग
अनाम रिकर्सन का उपयोग मुख्य रूप से अज्ञात कार्यों के लिए रिकर्सन की अनुमति देने में किया जाता है, खासकर जब वे क्लोजर (कंप्यूटर विज्ञान) बनाते हैं या फ़ंक्शन के नाम बंधन से बचने के लिए कॉलबैक (कंप्यूटर प्रोग्रामिंग) के रूप में उपयोग किए जाते हैं।
अनाम रिकर्सन में मुख्य रूप से वर्तमान फ़ंक्शन को कॉल करना शामिल है, जिसके परिणामस्वरूप प्रत्यक्ष रिकर्सन होता है। अनाम अप्रत्यक्ष रिकर्सन संभव है, जैसे कि कॉलर (पिछले फ़ंक्शन) को कॉल करके, या, शायद ही कभी, कॉल स्टैक में और ऊपर जाकर, और इसे पारस्परिक रिकर्सन उत्पन्न करने के लिए श्रृंखलाबद्ध किया जा सकता है। वर्तमान फ़ंक्शन का स्व-संदर्भ ऑब्जेक्ट ओरिएंटेड प्रोग्रामिंग में इस (कंप्यूटर प्रोग्रामिंग) कीवर्ड का कार्यात्मक समकक्ष है, जो किसी को वर्तमान संदर्भ को संदर्भित करने की अनुमति देता है।
अनाम रिकर्सन का उपयोग नामित फ़ंक्शंस के लिए भी किया जा सकता है, बल्कि उन्हें नाम से कॉल करना, यह निर्दिष्ट करना कि कोई वर्तमान फ़ंक्शन पर रिकर्सन कर रहा है, या किसी को उस नाम को बदलने की आवश्यकता के बिना फ़ंक्शन का नाम बदलने की अनुमति देना जहां यह स्वयं कॉल करता है। हालाँकि, प्रोग्रामिंग शैली के मामले में यह आम तौर पर नहीं किया जाता है।
विकल्प
नामित फ़ंक्शन
सामान्य विकल्प नामित फ़ंक्शंस और नामित रिकर्सन का उपयोग करना है। अनाम फ़ंक्शन को देखते हुए, यह या तो फ़ंक्शन में नाम बाइंड करके किया जा सकता है, जैसा कि जावास्क्रिप्ट में नामित फ़ंक्शन एक्सप्रेशन में होता है, या फ़ंक्शन को वेरिएबल में निर्दिष्ट करके और फिर वेरिएबल को कॉल करके किया जा सकता है, जैसा कि जावास्क्रिप्ट में फ़ंक्शन स्टेटमेंट में होता है। चूँकि जो भाषाएँ अनाम फ़ंक्शंस की अनुमति देती हैं, वे आम तौर पर इन फ़ंक्शंस को वेरिएबल्स (यदि प्रथम श्रेणी फ़ंक्शंस नहीं) को निर्दिष्ट करने की अनुमति देती हैं, तो कई भाषाएँ स्वयं फ़ंक्शन को संदर्भित करने का कोई तरीका प्रदान नहीं करती हैं, और स्पष्ट रूप से अनाम रिकर्सन को अस्वीकार करती हैं; उदाहरणों में गो (प्रोग्रामिंग भाषा) शामिल है।[1] उदाहरण के लिए, जावास्क्रिप्ट में फैक्टोरियल फ़ंक्शन को अज्ञात रिकर्सन के माध्यम से परिभाषित किया जा सकता है:[2]
[1, 2, 3, 4, 5].map(function(n) {
return (!(n > 1)) ? 1 : arguments.callee(n-1) * n;
});
नामित फ़ंक्शन अभिव्यक्ति का उपयोग करने के लिए पुनः लिखे जाने पर यह प्राप्त होता है:
[1, 2, 3, 4, 5].map(function factorial(n) {
return (!(n > 1)) ? 1 : factorial(n-1) * n;
});
फ़ंक्शंस को तर्क के रूप में पास करना
वर्तमान फ़ंक्शन या कॉलिंग फ़ंक्शन को संदर्भित करने के लिए तंत्र के बिना भी, ऐसी भाषा में अज्ञात रिकर्सन संभव है जो फ़ंक्शन को तर्क के रूप में अनुमति देता है। यह मूल पुनरावर्ती फ़ंक्शन में और पैरामीटर जोड़कर और पुनरावर्ती कॉल के लिए फ़ंक्शन के रूप में इस पैरामीटर का उपयोग करके किया जाता है। यह उच्च-क्रम फ़ंक्शन बनाता है, और इस उच्च फ़ंक्शन को पास करने से वास्तविक पुनरावर्ती फ़ंक्शन के भीतर अज्ञात रिकर्सन की अनुमति मिलती है। इस उच्च क्रम फ़ंक्शन पर निश्चित-बिंदु कॉम्बिनेटर लागू करके इसे पूरी तरह से गुमनाम रूप से किया जा सकता है। यह मुख्य रूप से अकादमिक रुचि का है, विशेष रूप से यह दिखाने के लिए कि लैम्ब्डा कैलकुलस में रिकर्सन है, क्योंकि परिणामी अभिव्यक्ति मूल नामित रिकर्सिव फ़ंक्शन की तुलना में काफी अधिक जटिल है। इसके विपरीत, फिक्स्ड-पॉइंटेड कॉम्बिनेटर्स के उपयोग को सामान्य रूप से अज्ञात रिकर्सन के रूप में संदर्भित किया जा सकता है, क्योंकि यह उनका उल्लेखनीय उपयोग है, हालांकि उनके पास अन्य अनुप्रयोग हैं।[3][4] इसे नीचे पायथन का उपयोग करके दर्शाया गया है। सबसे पहले, रिकर्सन नामक मानक:
def fact(n):
if n == 0:
return 1
return n * fact(n - 1)
उच्च-क्रम फ़ंक्शन का उपयोग करना ताकि शीर्ष-स्तरीय फ़ंक्शन किसी तर्क पर गुमनाम रूप से पुनरावृत्ति कर सके, लेकिन फिर भी तर्क के रूप में मानक पुनरावर्ती फ़ंक्शन की आवश्यकता होती है:
def fact0(n0):
if n0 == 0:
return 1
return n0 * fact0(n0 - 1)
fact1 = lambda f, n1: 1 if n1 == 0 else n1 * f(n1 - 1)
fact = lambda n: fact1(fact0, n)
हम फ़ंक्शन तर्क को कॉल में पास करके मानक पुनरावर्ती फ़ंक्शन को समाप्त कर सकते हैं:
fact1 = lambda f, n1: 1 if n1 == 0 else n1 * f(f, n1 - 1)
fact = lambda n: fact1(fact1, n)
दूसरी पंक्ति को सामान्य उच्च-क्रम फ़ंक्शन द्वारा प्रतिस्थापित किया जा सकता है जिसे संयोजनात्मक तर्क कहा जाता है:
F = lambda f: (lambda x: f(f, x))
fact1 = lambda f, n1: 1 if n1 == 0 else n1 * f(f, n1 - 1)
fact = F(fact1)
गुमनाम रूप से लिखा गया:[5]
(lambda f: (lambda x: f(f, x))) \
(lambda g, n1: 1 if n1 == 0 else n1 * g(g, n1 - 1))
लैम्ब्डा कैलकुलस में, जो केवल ही चर के कार्यों का उपयोग करता है, यह फिक्स्ड-पॉइंट कॉम्बिनेटर के माध्यम से किया जा सकता है। पहले दो वेरिएबल्स के उच्च-क्रम वाले फ़ंक्शन को एकल वेरिएबल का फ़ंक्शन बनाएं, जो करी द्वारा सीधे फ़ंक्शन लौटाता है:
fact1 = lambda f: (lambda n1: 1 if n1 == 0 else n1 * f(f)(n1 - 1))
fact = fact1(fact1)
यहां दो उच्च क्रम फ़ंक्शन को अपने आप में लागू करने वाले ऑपरेशन हैं: f(f)
पहली पंक्ति में और fact1(fact1)
क्षण में। कॉम्बिनेटरी लॉजिक में दूसरे दोहरे अनुप्रयोग का गुणनखंड करने से परिणाम मिलते हैं:
C = lambda x: x(x)
fact1 = lambda f: (lambda n1: 1 if n1 == 0 else n1 * f(f)(n1 - 1))
fact = C(fact1)
अन्य दोहरे अनुप्रयोग प्रतिफलों को ध्यान में रखते हुए:
C = lambda x: x(x)
D = lambda f: (lambda x: f(lambda v: x(x)(v)))
fact1 = lambda g: (lambda n1: 1 if n1 == 0 else n1 * g(n1 - 1))
fact = C(D(fact1))
दो कॉम्बिनेटरों को में मिलाने से फिक्स्ड-पॉइंट कॉम्बिनेटर प्राप्त होता है:
C = lambda x: x(x)
D = lambda f: (lambda x: f(lambda v: x(x)(v)))
Y = lambda y: C(D(y))
fact1 = lambda g: (lambda n1: 1 if n1 == 0 else n1 * g(n1 - 1))
fact = Y(fact1)
Y कॉम्बिनेटर का विस्तार करने से परिणाम मिलते हैं:
Y = lambda f: (lambda x: f(lambda v: x(x)(v))) \
(lambda x: f(lambda v: x(x)(v)))
fact1 = lambda g: (lambda n1: 1 if n1 == 0 else n1 * g(n1 - 1))
fact = Y(fact1)
इनके संयोजन से लैम्ब्डा कैलकुलस (एकल चर के अज्ञात कार्य) में फैक्टोरियल की पुनरावर्ती परिभाषा प्राप्त होती है:[6]
(lambda f: (lambda x: f(lambda v: x(x)(v)))
(lambda x: f(lambda v: x(x)(v)))) \
(lambda g: (lambda n1: 1 if n1 == 0 else n1 * g(n1 - 1)))
उदाहरण
एपीएल
एपीएल (प्रोग्रामिंग भाषा) में, वर्तमान डीएफएनएस तक पहुंच योग्य है ∇
. यह अज्ञात रिकर्सन की अनुमति देता है, जैसे कि फैक्टोरियल के इस कार्यान्वयन में:
{0=⍵:1 ⋄ ⍵×∇ ⍵-1} 5
120
{0=⍵:1 ⋄ ⍵×∇ ⍵-1}¨ ⍳10 ⍝ applied to each element of 0 to 9
1 1 2 6 24 120 720 5040 40320 362880
जावास्क्रिप्ट
जावास्क्रिप्ट में, वर्तमान फ़ंक्शन तक पहुंच योग्य है arguments.callee
, जबकि कॉलिंग फ़ंक्शन के माध्यम से पहुंच योग्य है arguments.caller
. ये अज्ञात रिकर्सन की अनुमति देते हैं, जैसे कि फैक्टोरियल के इस कार्यान्वयन में:[2]
[1, 2, 3, 4, 5].map(function(n) {
return (!(n > 1)) ? 1 : arguments.callee(n - 1) * n;
});
पर्ल
पर्ल 5.16 से शुरू होकर, वर्तमान सबरूटीन इसके माध्यम से पहुंच योग्य है __SUB__
टोकन, जो वर्तमान सबरूटीन का संदर्भ लौटाता है, या undef
सबरूटीन के बाहर.[7] यह अज्ञात रिकर्सन की अनुमति देता है, जैसे कि फैक्टोरियल के निम्नलिखित कार्यान्वयन में:
#!/usr/bin/perl
use feature ":5.16";
print sub {
my $x = shift;
$x > 0
? $x * __SUB__->( $x - 1 )
: 1;
}->(5), "\n";
आर
आर (प्रोग्रामिंग भाषा) में, वर्तमान फ़ंक्शन का उपयोग करके कॉल किया जा सकता है Recall
. उदाहरण के लिए,
sapply(0:5, function(n) {
if (n == 0) return(1)
n * Recall(n - 1)
})
हालाँकि, यह काम नहीं करेगा, यदि इसे किसी अन्य फ़ंक्शन के लिए तर्क के रूप में पारित किया जाता है, उदाहरण के लिए lapply
, अनाम फ़ंक्शन परिभाषा के अंदर। इस मामले में, sys.function(0)
इस्तेमाल किया जा सकता है।[8] उदाहरण के लिए, नीचे दिया गया कोड किसी सूची को पुनरावर्ती रूप से वर्गित करता है:
(function(x) {
if (is.list(x)) {
lapply(x, sys.function(0))
} else {
x^2
}
})(list(list(1, 2, 3), list(4, 5)))
संदर्भ
- ↑ Issue 226: It's impossible to recurse a anonymous function in Go without workarounds.
- ↑ 2.0 2.1 answer by olliej, Oct 25 '08 to "Why was the arguments.callee.caller property deprecated in JavaScript?", StackOverflow
- ↑ This terminology appear to be largely folklore, but it does appear in the following:
- Trey Nash, Accelerated C# 2008, Apress, 2007, ISBN 1-59059-873-3, p. 462—463. Derived substantially from Wes Dyer's blog (see next item).
- Wes Dyer Anonymous Recursion in C#, February 02, 2007, contains a substantially similar example found in the book above, but accompanied by more discussion.
- ↑ The If Works Deriving the Y combinator, January 10th, 2008
- ↑ Hugo Walter's answer to "Can a lambda function call itself recursively in Python?"
- ↑ Nux's answer to "Can a lambda function call itself recursively in Python?"
- ↑ Perldoc, "The 'current_sub' feature", perldoc feature
- ↑ agstudy's answer to Get currently called function to write anonymous recursive function at StackOverflow