paint-brush
मोजो लक्षण: उनकी तुलना गो इंटरफेस से कैसे की जाती है?द्वारा@a2svior
1,835 रीडिंग
1,835 रीडिंग

मोजो लक्षण: उनकी तुलना गो इंटरफेस से कैसे की जाती है?

द्वारा Valentin Erokhin6m2023/12/26
Read on Terminal Reader

बहुत लंबा; पढ़ने के लिए

उदाहरणों के साथ मोजो ट्रेट्स के साथ काम करने का एक पूर्वाभ्यास, और गो इंटरफेसेस से मोजो ट्रेट्स की तुलना। मोजो लक्षणों की सीमाएँ और चेतावनियाँ।
featured image - मोजो लक्षण: उनकी तुलना गो इंटरफेस से कैसे की जाती है?
Valentin Erokhin HackerNoon profile picture
0-item

हाल ही में मोजो में विशेषताएं पेश की गईं, इसलिए मैंने सोचा कि मैं उन्हें आज़माऊंगा। वर्तमान में, अंतर्निहित लक्षणों में CollectionElement , Copyable , Destructable , Intable , Movable , Sized , और Stringable शामिल हैं (ऐसा लगता है कि इन नामकरण परंपराओं में "-able" प्रत्यय एक चीज़ है!)।

लक्षण संरचनाओं पर काम करते हैं। किसी विशेषता को लागू करने के लिए, आप बस संरचना में एक विधि जोड़ते हैं जो विशेषता से मेल खाती है; फिर विशेषता नाम को पैरामीटर के रूप में पास करें:

 @value struct Duck(Quackable): fn quack(self): print("Quack!")


मोजो में @value डेकोरेटर __init__() , __copyinit__() और __moveinit__() जैसी जीवनचक्र विधियों को संरचना में सम्मिलित करता है, जिससे हमारा जीवन थोड़ा सरल हो जाता है क्योंकि हमें उन्हें स्वयं जोड़ने की आवश्यकता नहीं होती है।


मोजो में लक्षण अभी तक विधियों के लिए डिफ़ॉल्ट कार्यान्वयन का समर्थन नहीं करते हैं, इसलिए, उपरोक्त Quackable विधि के मुख्य भाग में ... आप pass भी उपयोग कर सकते हैं, जिसका प्रभाव Python जैसा ही होगा।

मोजो ट्रेट्स बनाम गो इंटरफेसेस

अलग-अलग नाम के बावजूद, मोजो में लक्षणों के लिए बुनियादी दृष्टिकोण मुझे गो इंटरफेस की याद दिलाता है। गो में, आप एक Duck संरचना को परिभाषित करेंगे और इस तरह एक Quackable इंटरफ़ेस लागू करेंगे:


 type Quackable interface { quack() }


और एक ऐसी संरचना बनाने के लिए जो इस इंटरफ़ेस को संतुष्ट करती हो:


 type Duck struct {} func (d Duck) quack() { fmt.Println("Quack!") }


इसकी तुलना मोजो कार्यान्वयन से करें:


 trait Quackable: fn quack(self): ... @value struct Duck(Quackable): fn quack(self): print("Quack!")


मुझे लगता है कि मोजो संस्करण और भी अधिक संक्षिप्त है, जो Duck संरचना प्रकार के अंदर quack() विधि परिभाषा को समाहित करता है। संरचनाओं पर काम करने के अलावा, मोजो में लक्षणों के लिए गो की तरह ही implements कीवर्ड की आवश्यकता नहीं होती है।


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


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

मोजो गुणों का उपयोग कैसे करें

लक्षण और इंटरफ़ेस का महत्व कोड को पुन: प्रयोज्य बनाना है। उदाहरण के लिए, मोजो में, आप ऐसे फ़ंक्शन लिख सकते हैं जो विशेषता प्रकारों को स्वीकार करते हैं...


 fn make_it_quack[T: Quackable](could_be_duck: T): could_be_duck.quack()


और फिर अलग-अलग संरचनाएं पास करें जो इनपुट के समान गुण को लागू करती हैं - सब कुछ बस काम करेगा! उदाहरण के लिए, यहां एक Goose संरचना है जो Quackable लागू करती है:


 @value struct Goose(Quackable): fn quack(self): print("Honk!")


और यहां, Goose और Duck दोनों पर make_it_quack कॉल करने के लिए (याद रखें, आपको अपने प्रोग्राम में प्रवेश बिंदु के रूप में मोजो में main फ़ंक्शन की आवश्यकता है):


 def main(): make_it_quack(Duck()) make_it_quack(Goose())


इसका आउटपुट होगा


 Quack! Honk!


लक्षण त्रुटियाँ

यदि मैंने कुछ ऐसा पारित करने का प्रयास किया है जो make_it_quack फ़ंक्शन में Quackable विशेषता को लागू नहीं करता है, मान लें कि StealthCow , प्रोग्राम संकलित नहीं होगा:


 @value struct StealthCow(): pass


 make_it_quack(StealthCow())


नीचे दिया गया त्रुटि संदेश अधिक वर्णनात्मक हो सकता था; शायद मोजो टीम इसमें सुधार करेगी?


 error: invalid call to 'make_it_quack': callee expects 1 input parameter, but 0 were specified


यदि मैं Goose से quack विधि हटा दूं तो भी ऐसा ही होगा; यहाँ, हमें एक अच्छी, वर्णनात्मक त्रुटि मिलती है:


 struct 'Goose' does not implement all requirements for 'Quackable' required function 'quack' is not implemented


शुद्ध पायथन दृष्टिकोण की तुलना में इस प्रकार की स्थैतिक प्रकार की जाँच का लाभ यह है कि हम त्रुटियों को आसानी से पकड़ सकते हैं और किसी भी गलती को उत्पादन में भेजने से बच सकते हैं क्योंकि कोड आसानी से संकलित नहीं होगा।

विरासत

मोजो में लक्षण पहले से ही वंशानुक्रम का समर्थन करते हैं, इसलिए हमारा `क्वैकएबल` गुण `श्रव्य` गुण का विस्तार इस प्रकार कर सकता है:


 trait Audible: fn make_sound(self): ...


 trait Quackable(Audible): fn quack(self): ...


इसका मतलब यह है कि Duck संरचना को Quackable विशेषता के अनुरूप होने के लिए quack और make_sound दोनों को लागू करना होगा।


यह गो में "इंटरफ़ेस एम्बेडिंग" की अवधारणा के समान है, जहां एक नया इंटरफ़ेस बनाने के लिए जो अन्य इंटरफ़ेस से प्राप्त होता है, आपको इस तरह से मूल इंटरफ़ेस एम्बेड करना होगा:


 type Quackable interface { Audible // includes methods of Audible in Quackable's method set }

स्थैतिक तरीके

लक्षण स्थिर तरीकों को भी स्वीकार करते हैं जो किसी संरचना का उदाहरण बनाए बिना काम करते हैं:


 trait Swims: @staticmethod fn swim(): ... @value struct Duck(Quackable, Swims): fn quack(self): print("Quack!") @staticmethod fn swim(): print("Swimming")


 fn make_it_swim[T: Swims](): T.swim()


आप इस प्रकार एक स्थिर विधि को कॉल करते हैं:


 def main(): make_it_quack(Duck()) make_it_quack(Goose()) Duck.swim()


जो आउटपुट देगा:


 Quack! Honk! Swimming


ध्यान दें कि अंतिम विधि कॉल में, डक इंस्टेंस नहीं बनाया गया है। ऑब्जेक्ट-ओरिएंटेड प्रोग्रामिंग से कुछ हद तक हटकर, पायथन में स्थिर विधियाँ इस प्रकार काम करती हैं। मोजो इस पायथन कार्यक्षमता पर आधारित है।

गो इंटरफेस की तुलना में मोजो लक्षणों की सीमाएं

दिलचस्प बात यह है कि एक खाली interface{} जो किसी भी प्रकार को पास करने की अनुमति देती है और गो जेनेरिक्स पेश किए जाने से पहले गो समुदाय के साथ लोकप्रिय थी, मोजो-टाइप किए गए फ़ंक्शन fn के साथ काम नहीं करेगी।


आपकी संरचना को __len__ या __str__ जैसी जीवनचक्र विधियों में से कम से कम एक को लागू करना होगा, जो इस मामले में, इसे Sized या Stringable के अनुरूप बनाएगा, जिसका उपयोग उन कार्यों के साथ किया जाएगा जो विशेषता प्रकारों को स्वीकार करते हैं।


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


अधिक सख्त मोजो fn फ़ंक्शन DynamicVector जैसे प्रकारों का उपयोग करके सामान्य संरचनाओं पर भी काम करते हैं; उसके बारे में और अधिक यहां पढ़ें ।


एक और सीमा जो मैं देखता हूं वह लक्षणों के बजाय संरचनाओं और उनकी विधियों से संबंधित है और स्वच्छ वास्तुकला को लागू करने/कोड को विभिन्न भागों में अलग करने में एक संभावित बाधा है।


गो बनाम मोजो संरचना विधि परिभाषा के साथ पिछले उदाहरणों में से एक पर विचार करें:


 type Duck struct {} func (d Duck) quack() { fmt.Println("Quack!") }


 @value struct Duck(Quackable): fn quack(self): print("Quack!")


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


हालाँकि यह कोई गंभीर अंतर नहीं है, बस जागरूक होने की बात है।


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