शुभ दिन, अभिभावक!
अपने पहले लेख में, मैं एक दिलचस्प बात के बारे में बात करना चाहूंगा जैसे कि कॉम्बिनेटर लाइब्रेरी। मैं सभी तर्कों को यथासंभव सरल और समझने योग्य बनाने की कोशिश करूंगा।
समस्या
दरअसल, कोई समस्या नहीं है, लेकिन बस कुछ दिलचस्प लिखने की इच्छा है। और मैंने व्युत्पन्न कार्यों को खोजने के लिए एक प्रणाली लिखने का फैसला किया (लेख
"डायनेमिक मैट। सी ++ में फ़ंक्शंस" और
"सी ++ टेम्प्लेट्स का उपयोग करके अणुओं की गणना") के साथ कुछ हद तक गूँजता है, लेकिन मैंने इसे प्रकाशित करने का फैसला किया, क्योंकि मुझे उम्मीद है कि इस पर प्रकाश डाला जाएगा। समस्या कुछ अलग है, और सभी उदाहरण c # में होंगे और c ++ में नहीं)।
वास्तव में,
कुछ भी तैयार करने की इच्छा नहीं थी, सभी अधिक तब पूरे उपक्रम का अर्थ खो जाएगा। और एक विचार का जन्म हुआ, मेरे अनुभवहीन मन के लिए असामान्य, जिसका कार्यान्वयन मैंने किया। थोड़ी देर बाद, गलती से "कॉम्बिनेटरियल लाइब्रेरी" के रूप में कार्यात्मक प्रोग्रामिंग के ऐसे पैटर्न के बारे में पढ़ा, मुझे एहसास हुआ कि यह वह था जिसे इसे लागू किया गया था। तो क्या है?
यह क्या है
एक कॉम्बीनेटरियल लाइब्रेरी संबंधित संस्थाओं का एक समूह है जो कि आदिम और कॉम्बिनेटर में विभाजित हैं।
- आदिम मूल, सरल, अविभाज्य इकाइयाँ हैं।
- संयोजक संस्थाओं को अधिक जटिल में संयोजित करने के तरीके हैं।
इसके अलावा, संस्थाओं के एक समूह के लिए,
बंद संपत्ति को पूरा किया जाना चाहिए:
"यौगिक इकाइयां आदिम से उपयोग के मामले में अलग नहीं होनी चाहिए।"
बहुत सार लगता है?
आइए गणितीय कार्यों और उनके डेरिवेटिव के उदाहरण को देखें।
सबसे पहले, आइए आदिमों के एक सेट को परिभाषित करते हैं।
प्राथमिकताओं, इस संदर्भ में, सबसे सरल कार्य करना चाहिए (मैं अपने स्वाद के लिए कुछ चुनूंगा):
और कॉम्बिनेटरों के कार्य के लिए, इस तरह के प्रसिद्ध संचालन के अलावा, गुणा, घटाव और विभाजन उपयुक्त हैं।
यह कैसे काम करता है?
सभी प्राथमिकताओं के लिए, हम डेरिवेटिव को स्वयं परिभाषित करते हैं। अगला, हम कॉम्बिनेटरों का वर्णन करते हैं।
कॉम्बिनर पर विचार करें "कार्यों के अलावा।"
यदि फ़ंक्शन f के व्युत्पन्न और फ़ंक्शन जी के व्युत्पन्न ज्ञात हैं, तो इन दो कार्यों के योग के व्युत्पन्न को खोजना आसान है: (f + g) '= f' + g '।
यही है, हम नियम बनाते हैं: कार्यों के योग की व्युत्पत्ति उनके व्युत्पत्ति का योग है।
हम इसी तरह शेष कॉम्बिनेटरों को परिभाषित करते हैं।
ठीक है, जैसे अमेरिका को अभी तक पता नहीं चला है, यह पता लगाना बाकी है कि इसे कोड में कैसे व्यक्त किया जाए।
अभ्यास
पूरे सिस्टम का मुख्य वर्ग सार क्लास होगा:
public abstract class Function { public abstract double Calc(double x); public abstract Function Derivative(); }
सब कुछ सरल है, फ़ंक्शन को बिंदु x पर इसके मूल्य को गिनने में सक्षम होना चाहिए, साथ ही इसके व्युत्पन्न को भी जानना होगा।
अगला, हम उन कार्यों को लागू करते हैं जिन्हें हमने चुना है।
सबसे पहले, निरंतर:
public class Constant : Function { public Constant(double val) { value = val; } public override double Calc(double val) { return value; } public override Function Derivative() { return new Constant(0); } private readonly double value; }
और फ़ंक्शन को रैखिक करें, या इसके सबसे सरल रूप को: f (x) = x। गणित में, इस तरह के मानचित्रण को समान कहा जाता है, इसलिए कक्षा को
"पहचान" कहा जाएगा।
public class Identity : Function { public override double Calc(double val) { return val; } public override Function Derivative() { return new Constant(1); } }
पहले से ही यहां आप इन दो वर्गों के कनेक्शन को नोटिस कर सकते हैं, अर्थात्, समान फ़ंक्शन का व्युत्पन्न स्थिर 1 है।
चलो अब कॉम्बिनेटरों के लिए एक वर्ग को परिभाषित करते हैं। अपनी बंद प्रकृति के कारण, यह सब कुछ आदिम के समान करने में सक्षम होना चाहिए, इसलिए इसे
फंक्शन क्लास से विरासत में प्राप्त करना तर्कसंगत है।
इस वर्ग के
संचालक को बुलाओ और इसे भी अमूर्त बनाओ।
public abstract class Operator : Function { protected Operator(Function a, Function b) { leftFunc = a; rightFunc = b; } protected readonly Function leftFunc; protected readonly Function rightFunc; }
और यह भी, उदाहरण के लिए, हम कॉम्बिनेटर "गुणन" को परिभाषित करते हैं, बाकी समान तरीके से परिभाषित किए जाते हैं।
public class Multiplication : Operator { public Multiplication(Function a, Function b) : base(a, b) { } public override double Calc(double val) { return leftFunc.Calc(val) * rightFunc.Calc(val); } public override Function Derivative() { return leftFunc.Derivative() * rightFunc + leftFunc * rightFunc.Derivative(); } }
मुझे उम्मीद है कि सब कुछ स्पष्ट है, हमने एक फ़ंक्शन को दूसरे से गुणा करके फ़ंक्शन के निर्माण के लिए स्पष्ट रूप से वर्णित किया है।
एक्स पर इस तरह के एक फ़ंक्शन का मूल्य जानने के लिए, आपको एक्स में एक का मूल्य, फिर दूसरे और फिर इन मूल्यों को गुणा करने की आवश्यकता है।
दो कार्यों के उत्पाद के व्युत्पन्न को निम्नानुसार परिभाषित किया गया है: (f * g) '= f' * g + g '* f।
प्रमाण :)कोड में, हमने एक में एक लिखा था जो हम शब्दों में बात कर रहे थे।
कूल? मेरी राय में, हाँ!
इसी तरह, हम अतिरिक्त कॉम्बीनेटर -
एडिशन क्लास को परिभाषित करते हैं, मैं इस लेख में कोड नहीं दूंगा, यह लगभग पूरी तरह से गुणा के लिए कोड को दोहराता है।
आइए अब फ़ंक्शन (x) = 2x + 3 लिखने के लिए इन विधियों का उपयोग करने का प्रयास करें।
var f = new Addition(new Multiplication(new Constant(2), new Identity()), new Constant(3)); var x = f.Calc(2)
वाह, कितना बढ़िया!
खाने के बाद मिठाई
वास्तव में अच्छा नहीं है। मैं खुद को गोली मारता अगर किसी भी, यहां तक कि सबसे सरल कार्य के लिए, मुझे ऐसा कुछ लिखना होगा। सौभाग्य से, सी # सिंटैक्टिक शुगर हमारी मदद करेगी।
हम
फंक्शन क्लास में निम्नलिखित तरीके जोड़ते हैं।
public static Function operator +(Function a, Function b) { return new Addition(a, b); } public static Function operator +(double k, Function b) { return new Constant(k) + b; }
यह हमें क्या देता है? और अब इसके बजाय:
new Addition(new Constant(2), new Identity())
आप इस तरह लिख सकते हैं:
2 + new Identity()
यह पहले से थोड़ा बेहतर लग रहा है।
हम शेष संचालन (*, +, -) के लिए समान ऑपरेटरों को परिभाषित करते हैं।
अब, हर बार एक नया फ़ंक्शन ऑब्जेक्ट नहीं बनाने के लिए, हम एक स्थिर वर्ग लिखेंगे जिसमें हम कुछ अक्सर उपयोग किए जाने वाले कार्यों को जगह देंगे। इस वर्ग को मैंने
फंक कहा।
मैंने कुछ और कार्यों को भी परिभाषित किया है, जैसे साइन, कोसाइन और एक्सपोनेंट। यहाँ क्या हुआ:
public static class Funcs { public static readonly Function Id = new Identity(); public static readonly Function Exp = new Exponenta(); public static readonly Function Zero = new Constant(0); public static readonly Function Sin = new Sinus(); public static readonly Function Cos = new Cosinus(); public static readonly Function Tan = Sin / Cos; public static readonly Function Ctg = Cos / Sin; public static readonly Function Sh = (Exp - 1 / Exp) / 2; public static readonly Function Ch = (Exp + 1 / Exp) / 2; public static readonly Function Tgh = Sh / Ch; public static readonly Function Cth = Sh / Ch; }
जैसा कि आप देख सकते हैं, मैंने पिछले 6 कार्यों को "आदिम कार्यों" के संयोजन के रूप में परिभाषित किया है।
अब हम फ़ंक्शन f (x) = 2x + 3 निर्धारित करने के लिए फिर से कोशिश कर सकते हैं।
var f = 2 * Funcs.Id + 3; var x = f.Calc(2)
वैसे कैसे? मेरी राय में, इस तरह की प्रणाली का उपयोग करना बहुत आसान हो गया है।
निष्कर्ष
इस दृष्टिकोण के पेशेवरों और विपक्ष क्या हैं?
एक स्पष्ट प्लस एक्स्टेंसिबिलिटी है। वास्तव में, अपने कार्य को जोड़ना मुश्किल नहीं होगा, उदाहरण के लिए, लघुगणक कार्य, और व्युत्पन्न के माध्यम से कक्षाओं की सामान्य प्रणाली में शामिल करने के लिए।
नुकसान में फ़ंक्शन का तेजी से विकास शामिल है, जब व्युत्पन्न ढूंढते हैं, उदाहरण के लिए, फ़ंक्शन f (x) = x ^ 100 (100 की शक्ति के लिए x), 10 व्युत्पन्न को ढूंढना एक बहुत समय लेने वाला ऑपरेशन है - मेरे पास इसे पूरा करने के लिए इंतजार करने का धैर्य नहीं है।
संदर्भ
जुझारू पुस्तकालयों के बारे में । मैं उन सभी के संदर्भ में एक लेख प्रस्तुत करता हूं जो कार्यात्मक प्रोग्रामिंग में रुचि रखते हैं, मुख्य रूप से वे जो इससे पहले आए हैं - यह एफपी में मुख्य दृष्टिकोणों के बारे में बताता है, और उदाहरण देता है। IMHO, लेख सही ढंग से बना है और दिलचस्प रूप से लिखा गया है - यह पढ़ने में खुशी है।
गिथब पर प्रोजेक्ट यदि आप लेख में रुचि रखते हैं, तो आप प्रोजेक्ट के स्रोत कोड को जीथब से डाउनलोड कर सकते हैं, वहां फंक्शंस कॉम्बिनेटर के संयोजन को भी लागू किया जाता है, टुकड़ा-परिभाषित कार्य जोड़ा जाता है, कार्यों का सरलतम एकीकरण और कुछ अनुकूलन लिखे जाते हैं - सामान्य रूप से, सब कुछ जो लेख में फिट नहीं हुआ था
PS जब मैं इस लेख को हब पर तैयार कर रहा था, तो इसी तरह के विषयों पर 2 और दिखाई दिए:
“डायनेमिक मैट। C ++ में कार्य " और
C ++ में टेम्प्लेट की मदद से व्युत्पन्न की गणना" , मुझे आशा है कि मेरा अतिश्योक्ति नहीं होगी और फेरीवाले इसे ब्याज के साथ लेंगे।
व्यक्तिगत में लिखने के लिए व्याकरण और वर्तनी त्रुटियों के बारे में अनुरोध।