"... जो लोग शौकिया तौर पर मूर्ख को दोषी ठहराते हुए घूरने से बाज नहीं आते हैं, उन्हें यह देखने को मिलता है कि मैं कैसे साबित करता हूं कि जावा और विजुअल बेसिक जन्म के समय जुड़वाँ बच्चे हैं, और सी ++ वे दूर के रिश्तेदार भी नहीं हैं।"ब्रूस मैकिननी "डाई हार्ड बेसिक बेसिक"परिचय
कार्यात्मक प्रोग्रामिंग दृष्टिकोणों में एक निरंतर रुचि वर्तमान में इस तथ्य की ओर ले जाती है कि पारंपरिक प्रोग्रामिंग भाषाएं सक्रिय रूप से कार्यात्मक साधन प्राप्त कर रही हैं। और यद्यपि शुद्ध कार्यात्मक भाषाएं अभी भी बहुत लोकप्रिय नहीं हैं, लेकिन कार्यक्षमता C ++, Java, JavaScript, Python, और अन्य भाषाओं में मजबूती से स्थापित है। VBA भाषा Microsoft Office उपयोगकर्ताओं के काफी बड़े दर्शकों के साथ कई वर्षों से लोकप्रिय रही है। इस भाषा में व्यावहारिक रूप से कोई कार्यात्मक उपकरण नहीं है।
आइए इस अंतर को भरने की कोशिश करें - मैं VBA द्वारा लागू कार्यात्मक इंटरफेस के पूर्ण (हालांकि शायद सही नहीं) का प्रस्ताव करता हूं। कार्यान्वयन बाद के शोधन और सुधार के आधार के रूप में कार्य कर सकता है।
कार्यात्मक तर्क समस्या
इस रास्ते पर आने वाली पहली समस्या एक फ़ंक्शन या विधि के लिए कार्यात्मक तर्कों को पारित करने की समस्या है। VBA भाषा में उपयुक्त उपकरण नहीं हैं (AddressOf ऑपरेटर केवल Windows API फ़ंक्शन के लिए पते स्थानांतरित करने के लिए कार्य करता है और उपयोग करने के लिए पूरी तरह से सुरक्षित नहीं है)। उसी को पॉइंटर द्वारा कॉलिंग फ़ंक्शन की प्रसिद्ध विधि के बारे में कहा जा सकता है (जी। मैगडानुरोव विजुअल बेसिक इन प्रैक्टिस सेंट पीटर्सबर्ग: "बीएचवी पीटर्सबर्ग", 2008)। चलो जोखिम नहीं लेते हैं - हम कार्यान्वयन में केवल मानक भाषा सुविधाओं और मानक पुस्तकालयों का उपयोग करते हैं।
दुर्भाग्य से, यहां पीएलओ ज्यादा मदद नहीं करता है। किसी कार्य या फ़ंक्शन में एक कार्यात्मक ऑब्जेक्ट को स्थानांतरित करने के लिए, VBA एक मानक अवसर प्रदान करता है - ऑब्जेक्ट शेल के साथ आवश्यक कार्यक्षमता को लपेटने के लिए (ऑब्जेक्ट बनाएं, जिसमें से एक विधि आवश्यक कार्यक्षमता होगी)। ऑब्जेक्ट को पैरामीटर के रूप में पारित किया जा सकता है। यह दृष्टिकोण व्यावहारिक है, लेकिन बहुत भारी है - प्रत्येक आवश्यक कार्यक्षमता के लिए आपको अपनी कक्षा और इस वर्ग की एक वस्तु बनानी होगी।
एक और तरीका है, जो बहुत सरल है और प्रत्येक कार्यक्षमता के लिए अलग-अलग वर्गों के निर्माण की आवश्यकता नहीं है।
मान लीजिए कि आप एक निश्चित खरीद प्रक्रिया के लिए एक अनाम फ़ंक्शन पास करना चाहते हैं जो एक-एक करके इसके तर्क को बढ़ाता है। इस फ़ंक्शन को निम्नानुसार लिखा जा सकता है:
x -> x+1
अनाम फ़ंक्शंस असाइन करने की यह धारणा अब लगभग "वास्तविक मानक" बन गई है। एक पैरामीटर को ऐसे फ़ंक्शन को पास करने का एकमात्र तरीका स्ट्रिंग प्रतिनिधित्व का उपयोग करना है:
r=proc(a,b,”x->x+1”)
यहाँ a और b साधारण पैरामीटर हैं, और तीसरा पैरामीटर एक अनाम फ़ंक्शन है, जो बहुत स्पष्ट है और लोकप्रिय प्रोग्रामिंग भाषाओं में प्रविष्टियों से बहुत कम है।
इस तरह परिभाषित एक अनाम फ़ंक्शन का उपयोग करने के लिए, आपको पहले इसे VBA फ़ंक्शन के मानक रूप में लाना होगा। यह निम्नलिखित उपयोगिता प्रक्रिया करता है:
Private Function prepCode(Code As String) As String k% = InStr(Code, "->") parms$ = Trim$(Left$(Code, k% - 1)) body$ = Mid$(Code, k% + 2) If Left$(parms$, 1) <> "(" Then parms$ = "(" + parms$ + ")" If InStr(body$, "self") = 0 Then body$ = ";self=" & body$ & ";" body$ = Replace(body$, ";", vbCrLf) prepCode = "function self" & parms & vbCrLf & body & _ vbCrLf & "end function" End Function
फ़ंक्शन मापदंडों और गणना निकाय की एक सूची का चयन करता है, और फिर एक फ़ंक्शन बनाता है जिसे स्वयं कहा जाता है। हमारे मामले के लिए, स्वयं कार्य के निम्नलिखित रूप होंगे:
function self(x) self=x+1 End function
जाहिर है, VBA सिंटैक्स के अनुसार, यह फ़ंक्शन वही करेगा जो अनाम फ़ंक्शन को करना चाहिए था - इसके तर्क के मूल्य को 1. से बढ़ाएं। यह फ़ंक्शन अभी तक VBA फ़ंक्शन नहीं है, लेकिन केवल एक पंक्ति है जिसमें निर्दिष्ट कोड है। किसी फ़ंक्शन में स्ट्रिंग को चालू करने के लिए, आप मानक Microsoft लाइब्रेरी "Msscript.ocx" का उपयोग कर सकते हैं। यह COM लाइब्रेरी आपको स्ट्रिंग रूप में निर्दिष्ट मनमाने ढंग से VBA कोड को निष्पादित करने की अनुमति देता है। ऐसा करने के लिए, निम्न कार्य करें:
- एक ScriptControl ऑब्जेक्ट बनाएँ
- भाषा स्थापना विधि (VBScript) को कॉल करें;
- फ़ंक्शन लोडिंग विधि को कॉल करें;
- कॉल करने के लिए eval मेथड को कॉल करें।
यह सब कुछ इस तरह दिखता है:
Set locEv=new ScriptControl locEv.Language = "VBScript" locEv.AddCode prepCode(“x->x+1”) r=locEv.eval(“self(5)”)
इस कोड को निष्पादित करने के बाद, चर आर का मूल्य 6 होगा।
यहां तीन बिंदु बनाए जाने चाहिए:
- एक अनाम फ़ंक्शन के शरीर में कई लाइनें हो सकती हैं। इस मामले में व्यक्तिगत बयान एक अर्धविराम के साथ समाप्त होते हैं। अंतिम कोड से, वर्ण ";" बाहर रखा गया है। एक बहु-पंक्ति निकाय आपको अनाम कार्यों में बहुत उन्नत कार्यक्षमता को लागू करने की अनुमति देता है;
- तथ्य यह है कि अनाम फ़ंक्शन "वास्तव में" का नाम "स्वयं" है एक अप्रत्याशित बोनस देता है - एक अनाम फ़ंक्शन पुनरावर्ती हो सकता है।
- चूंकि ScriptControl ऑब्जेक्ट दो भाषाओं - VBScript और Jscript का समर्थन करता है, अनाम फ़ंक्शन Jscript में लिखा जा सकता है (सैद्धांतिक रूप से) (जो लोग इसे आज़मा सकते हैं)।
अगला, एक वस्तु कार्यान्वयन मॉडल का वर्णन किया जाएगा।
ऑब्जेक्ट मॉडल
मॉडल का आधार दो प्रकार की वस्तुएं हैं: कंटेनर और जेनरेटर। कंटेनर ऑब्जेक्ट मनमाना आकार के एक सरणी का एक भंडार है, जेनरेटर ऑब्जेक्ट, जैसा कि नाम का अर्थ है, एक सामान्य रूप जनरेटर को लागू करता है।
दोनों ऑब्जेक्ट aIter इंटरफ़ेस को लागू करते हैं, जिसे नीचे और अधिक विवरण में वर्णित किया गया है। इंटरफ़ेस में 19 कार्य शामिल हैं:
जेनरेटर ऑब्जेक्ट के लिए, कई तरीके सीधे लागू नहीं होते हैं - आपको पहले एक कंटेनर में कुछ निश्चित मानों का चयन करना होगा। जब जनरेटर के लिए एक असत्य विधि को कॉल करने की कोशिश की जाती है, तो कोड 666 के साथ एक त्रुटि उत्पन्न होती है। इसके बाद, वर्णित इंटरफेस का उपयोग करने के कई उदाहरणों पर विचार किया जाएगा।
उदाहरण
लगातार संख्या फाइबोनैचि मुद्रण:
Sub Test_1() Dim fibGen As aIter Set fibGen = New Generator fibGen.Init Array(1, 0), "(c,p)->c+p" For i% = 1 To 50 Debug.Print fibGen.getNext() Next i% End Sub
यहां एक जनरेटर प्रारंभिक मान 0 और 1 के साथ बनाया गया है और फाइबोनैचि अनुक्रम के अनुरूप एक जनरेटिंग फ़ंक्शन है। अगला, पहले 50 नंबर एक लूप में मुद्रित होते हैं।
मानचित्र और फ़िल्टर:
Sub Test_2() Dim co As aIter Dim Z As aIter Dim w As aIter Set co = New Container co.Init frange(1, 100) Set Z = co.map("x -> 1.0/x"). _ take(20).filter(" x -> (x>0.3) or (x<=0.1)") iii% = 1 Do While Z.hasNext() Debug.Print iii%; " "; Z.getNext() iii% = iii% + 1 Loop End Sub
एक कंटेनर 1 से 100 तक की सीमा से एक संख्यात्मक अनुक्रम द्वारा बनाया और शुरू किया जाता है। अगला, नक्शे के साथ संख्याओं को उलटा द्वारा प्रतिस्थापित किया जाता है। इनमें से, पहले बीस लिया जाता है। फिर इस आबादी को फ़िल्टर्ड किया जाता है और 0.1 से कम या 0.1 से बड़ी संख्या का चयन किया जाता है। परिणाम कंटेनर में लौटाया जाता है, जिसकी रचना मुद्रित होती है।
दृढ़ संकल्प का उपयोग करना:
Sub Test_4() Dim co As aIter Set co = New Container co.Init frange(1, 100) v = co.reduce(0, "(acc,x)->acc+x") Debug.Print v v = co.reduce(1, "(acc,x)->acc*x") Debug.Print v End Sub
यहां, दृढ़ संकल्प का उपयोग करते हुए, 1 से 100 तक की संख्याओं के योग और उत्पाद पर विचार किया जाता है।
Sub Test_5() Dim co1 As aIter Dim co2 As aIter Dim co3 As aIter Set co1 = New Generator co1.Init Array(123456789), "x -> INT(x/10)" Set co2 = co1.takeWhile(100, "x -> x > 0") Set co3 = co2.map("x -> x mod 10") Debug.Print co3.maximun Debug.Print co3.minimum Debug.Print co3.summa Debug.Print co3.production End Sub
इस उदाहरण में, जनरेटर को 1 का निर्माण किया जाता है, क्रमिक रूप से मूल संख्या को 10 डिग्री से विभाजित करना। फिर शून्य दिखाई देने तक कोटियों का चयन किया जाता है। उसके बाद, 10. के द्वारा विभाजन के शेष भाग लेने के कार्य द्वारा परिणामकों की परिणामी सूची प्रदर्शित की जाती है। परिणाम संख्या के अंकों की एक सूची है। सूची सारांशित है, उसने अधिकतम, न्यूनतम और उत्पाद की गणना की।
निष्कर्ष
प्रस्तावित दृष्टिकोण काफी व्यावहारिक है और एक कार्यात्मक शैली में VBA- प्रोग्रामर के रोजमर्रा के कार्यों को हल करने के लिए सफलतापूर्वक लागू किया जा सकता है। हम जावेदों से बदतर क्यों हैं?
यहाँ उदाहरण डाउनलोड
करेंगुड लक !!!