पायथन की "कार्यात्मक" जड़ें कहां से आती हैं?

मैंने कभी नहीं सोचा था कि लोग जो भी कहते हैं या सोचते हैं, उसके बावजूद पायथन कार्यात्मक भाषाओं से प्रभावित होगा। मैं C और Algol68 जैसी अनिवार्य भाषाओं से परिचित हूं, और हालांकि मैंने फ़ंक्शन "प्रथम श्रेणी" ऑब्जेक्ट बनाया है, मैंने पायथन को एक कार्यात्मक प्रोग्रामिंग भाषा के रूप में नहीं देखा। हालांकि, यह स्पष्ट था कि उपयोगकर्ता सूचियों और सुविधाओं से अधिक चाहते थे।

सूची संचालन को प्रत्येक सूची आइटम पर लागू किया गया और एक नई सूची बनाई गई। उदाहरण के लिए:
def square(x): return x*x vals = [1, 2, 3, 4] newvals = [] for v in vals: newvals.append(square(v)) 

लिस्प और स्कीम जैसी कार्यात्मक भाषाओं में, इस तरह के संचालन को भाषा के अंतर्निहित कार्यों के रूप में डिजाइन किया गया था। इस प्रकार, ऐसी भाषाओं से परिचित उपयोगकर्ता पायथन में समान कार्यक्षमता लागू करते हैं। उदाहरण के लिए:
 def map(f, s): result = [] for x in s: result.append(f(x)) return result def square(x): return x*x vals = [1, 2, 3, 4] newvals = map(square,vals) 

उपरोक्त कोड की सूक्ष्मता यह है कि कई लोग इस तथ्य को पसंद नहीं करते थे कि एक फ़ंक्शन को अलग-अलग कार्यों के सेट के रूप में आइटम को सूचीबद्ध करने के लिए लागू किया जाता है। मैपिंग के दौरान लिस्प जैसी भाषाओं को "मक्खी पर" परिभाषित करने की अनुमति दी जाती है। उदाहरण के लिए, स्कीम में, आप नीचे दिए गए अनुसार लंबो का उपयोग करके अनाम फ़ंक्शन बना सकते हैं और एकल अभिव्यक्ति में मैपिंग कर सकते हैं:
 (map (lambda (x) (* xx)) '(1 2 3 4)) 

हालाँकि पायथन में "फस्र्ट क्लास" ऑब्जेक्ट थे, लेकिन अनाम कार्यों को बनाने के लिए ऐसा कोई तंत्र नहीं था।

1993 के अंत में, उपयोगकर्ताओं ने गुमनाम कार्यों को बनाने के लिए विभिन्न विचारों के बारे में बताया। उदाहरण के लिए, मार्क लुत्ज़ ने एक फ़ंक्शन के लिए कोड लिखा था जो निष्पादन का उपयोग करके फ़ंक्शन बनाता है:
 def genfunc(args, expr): exec('def f(' + args + '): return ' + expr) return eval('f') # Sample usage vals = [1, 2, 3, 4] newvals = map(genfunc('x', 'x*x'), vals) 

टिम पीटर्स ने समाधान का एक समाधान लिखा जो वाक्य रचना को सरल बनाता है, जिससे उपयोगकर्ताओं को निम्नलिखित की अनुमति मिलती है:
 vals = [1, 2, 3, 4] newvals = map(func('x: x*x'), vals) 


यह स्पष्ट हो गया कि वास्तव में ऐसी कार्यक्षमता की आवश्यकता थी। उसी समय, कोड की पंक्तियों के रूप में अनाम कार्यों को परिभाषित करने के लिए यह आकर्षक लग रहा था कि प्रोग्रामर को मैन्युअल रूप से निष्पादन के माध्यम से प्रक्रिया करना होगा। इस प्रकार, जनवरी 1994 में, मानक पुस्तकालय में मानचित्र (), फ़िल्टर (), और कम () फ़ंक्शन जोड़े गए। इसके अलावा, एक लैम्ब्डा ऑपरेटर को अधिक प्रत्यक्ष सिंटैक्स में अनाम फ़ंक्शन (जैसे भाव) बनाने के लिए पेश किया गया था। उदाहरण के लिए:
 vals = [1, 2, 3, 4] newvals = map(lambda x:x*x, vals) 

ये परिवर्धन विकास के प्रारंभिक चरण में महत्वपूर्ण थे। दुर्भाग्य से, मुझे लेखक याद नहीं है, और एसवीएन लॉग ने इसे रिकॉर्ड नहीं किया। यदि यह आपकी योग्यता है, तो एक टिप्पणी छोड़ दें!

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

अनाम कार्यों को परिभाषित करने के लिए लैम्ब्डा का वास्तव में केवल वाक्यगत चीनी होने का इरादा था। हालाँकि, शब्दावली के इस विकल्प के कई अनपेक्षित परिणाम थे। उदाहरण के लिए, कार्यात्मक भाषाओं से परिचित उपयोगकर्ता अन्य भाषाओं के मेल से लैम्बडा शब्दार्थ की अपेक्षा करते हैं। नतीजतन, उन्होंने पाया कि पायथन कार्यान्वयन में उन्नत कार्यक्षमता की बहुत कमी थी। उदाहरण के लिए, लैम्ब्डा के साथ समस्या यह है कि प्रदान की गई अभिव्यक्ति आसपास के संदर्भ में चर तक नहीं पहुंच सकती है। उदाहरण के लिए, यदि आपके पास यह कोड है, तो नक्शा () निरस्त हो जाएगा क्योंकि लंबो फ़ंक्शन चर 'a' के अपरिभाषित संदर्भ के साथ काम करेगा।
 def spam(s): a = 4 r = map(lambda x: a*x, s) 

इस समस्या के लिए वर्कअराउंड थे, लेकिन उनमें "डिफ़ॉल्ट तर्क" का उपयोग करना और लंबोदर अभिव्यक्ति के लिए छिपे हुए मापदंडों को शामिल करना शामिल था। उदाहरण के लिए:
 def spam(s): a = 4 r = map(lambda x, a=a: a*x, s) 


आंतरिक कार्यों के लिए इस समस्या का "सही" समाधान फ़ंक्शन संदर्भ के लिए सभी स्थानीय चरों के संदर्भों को संक्षेप में स्थानांतरित करना था। यह दृष्टिकोण क्लोजर के रूप में जाना जाता है और कार्यात्मक भाषाओं का एक महत्वपूर्ण पहलू है। हालाँकि, इस फीचर को संस्करण 2.2 की रिलीज़ तक पायथन में पेश नहीं किया गया था।

उत्सुकता से, नक्शे, फ़िल्टर, और उन कार्यों को कम करते हैं जो मूल रूप से लैम्ब्डा और अन्य कार्यात्मकताओं की शुरूआत को प्रेरित करते थे, उन्हें मोटे तौर पर "सूची समझ" और जनरेटर द्वारा प्रतिस्थापित किया गया था। वास्तव में, पायथन 3.0 में अंतर्निहित फ़ंक्शन की सूची से कम फ़ंक्शन को हटा दिया गया है।

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

अंत में, भले ही कई कार्यात्मक प्रोग्रामिंग विशेषताओं को पिछले कुछ वर्षों में पेश किया गया है, पाइथन में अभी भी "वास्तविक" कार्यात्मक भाषाओं से कुछ कार्यक्षमता का अभाव है। उदाहरण के लिए, पायथन कुछ प्रकार के अनुकूलन (जैसे पूंछ पुनरावृत्ति) नहीं करता है। पायथन की गतिशील प्रकृति ने कार्यात्मक भाषाओं में ज्ञात संकलन-समय अनुकूलन को हास्केल या एमएल के रूप में पेश करना असंभव बना दिया।

Source: https://habr.com/ru/post/In111756/


All Articles