उपयोगकर्ता-परिभाषित ऑपरेटर अधिक सामान्य क्यों नहीं हैं?


94

एक विशेषता जो मुझे कार्यात्मक भाषाओं से याद आती है वह यह है कि ऑपरेटर केवल कार्य करते हैं, इसलिए एक कस्टम ऑपरेटर को जोड़ना अक्सर फ़ंक्शन जोड़ने के रूप में सरल होता है। कई प्रक्रियात्मक भाषाएं ऑपरेटर को ओवरलोड करने की अनुमति देती हैं, इसलिए कुछ अर्थों में ऑपरेटर अभी भी कार्य करते हैं (यह डी में बहुत सही है जहां ऑपरेटर को टेम्पलेट पैरामीटर में स्ट्रिंग के रूप में पारित किया जाता है)।

ऐसा लगता है कि जहां ऑपरेटर ओवरलोडिंग की अनुमति है, अक्सर अतिरिक्त, कस्टम ऑपरेटरों को जोड़ने के लिए तुच्छ है। मुझे यह ब्लॉग पोस्ट मिला , जो तर्क देता है कि कस्टम ऑपरेटर पूर्ववर्ती नियमों के कारण infix संकेतन के साथ अच्छी तरह से काम नहीं करते हैं, लेकिन लेखक इस समस्या के कई समाधान देता है।

मैंने चारों ओर देखा और कोई भी प्रक्रियात्मक भाषा नहीं खोज सका जो भाषा में कस्टम ऑपरेटरों का समर्थन करती हो। हैक (जैसे C ++ में मैक्रोज़) हैं, लेकिन यह शायद ही भाषा समर्थन के समान है।

चूंकि यह सुविधा लागू करने के लिए बहुत तुच्छ है, इसलिए यह अधिक सामान्य नहीं है?

मैं समझता हूं कि यह कुछ बदसूरत कोड को जन्म दे सकता है, लेकिन इसने भाषा डिजाइनरों को अतीत में उपयोगी सुविधाओं को जोड़ने से नहीं रोका है जिन्हें आसानी से दुरुपयोग किया जा सकता है (मैक्रोज़, टर्नरी ऑपरेटर, असुरक्षित पॉइंटर्स)।

वास्तविक उपयोग के मामले:

  • लापता परिचालकों को लागू करें (जैसे कि Lua में बिटवाइज़ ऑपरेटर नहीं हैं)
  • मिमिक डी ~(सरणी संयोजन)
  • DSLs
  • |यूनिक्स पाइप-स्टाइल सिंटैक्स शुगर के रूप में उपयोग करें (कोरटाइन / जनरेटर का उपयोग करके)

मैं भी भाषाओं कि में दिलचस्पी रखता हूँ कर कस्टम ऑपरेटरों की अनुमति देते हैं, लेकिन मैं में अधिक रुचि रखते कर रहा हूँ क्यों यह बाहर रखा गया है। मैंने उपयोगकर्ता-परिभाषित ऑपरेटरों को जोड़ने के लिए एक स्क्रिप्टिंग भाषा को फोर्क करने के बारे में सोचा था, लेकिन जब मैंने महसूस किया कि मैंने इसे कहीं भी नहीं देखा है, तो खुद को रोक दिया है, इसलिए शायद एक अच्छा कारण है कि भाषा डिजाइनर मुझसे ज्यादा स्मार्ट नहीं हैं।


4
वहाँ एक है रेडिट चर्चा इस प्रश्न के बारे चल रहा है।
डायनामिक

2
@dimatura: मैं R के बारे में बहुत कुछ नहीं जानता, लेकिन यह कस्टम ऑपरेटर अभी भी बहुत लचीला नहीं लगता है (जैसे कोई उचित तरीका नहीं है कि इसे ठीक करना, दायरा, ओवरलोडिंग इत्यादि को परिभाषित करें), जो बताता है कि उनका उपयोग क्यों नहीं किया जाता है। यह अन्य भाषाओं में भिन्न है, निश्चित रूप से हास्केल में जो कस्टम इन्फिक्स ऑपरेटरों का बहुत उपयोग करती है । प्रक्रियात्मक भाषा का एक अन्य उदाहरण यथोचित कस्टम-इन्फिक्स समर्थन के साथ निमरोड है , और निश्चित रूप से पर्ल उन्हें भी अनुमति देता है
leftaroundabout

4
दूसरा विकल्प है, लिस्प वास्तव में ऑपरेटरों और कार्यों के बीच कोई अंतर नहीं है।
दाढ़ी

4
प्रोलॉग का अभी तक कोई उल्लेख नहीं किया गया है, एक और भाषा जहां ऑपरेटर केवल कार्यों के लिए सिंटैक्टिक चीनी हैं (हां गणित भी) और जो आपको कस्टम ऑपरेटरों को कस्टम पूर्वता के साथ परिभाषित करने की अनुमति देता है।
डेविड काउडेन

2
@BeardedO, लिस्प में कोई भी इन्फिक्स ऑपरेटर नहीं हैं। एक बार जब आप उन्हें पेश करते हैं, तो आपको पूर्ववर्ती और इस तरह के सभी मुद्दों से निपटना होगा।
एसके-लॉजिक

जवाबों:


134

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

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


23
दो विचारधारायें, पर plus.google.com/110981030061712822816/posts/KaSKeg4vQtz भी +1 के प्रश्न के सबसे सीधा (और संभावना सबसे सही) जवाब होने के लिए क्यों भाषा डिजाइनरों अन्य बनाम एक चुनें। मैं यह भी कहूंगा कि आपकी थीसिस के आधार पर आप इसे कम कर सकते हैं कि कम भाषाएं इसे अनुमति देती हैं क्योंकि डेवलपर्स का एक छोटा हिस्सा अन्यथा की तुलना में अत्यधिक कुशल है (किसी भी चीज़ का शीर्ष प्रतिशत हमेशा परिभाषा से अल्पसंख्यक होगा)
जिमी हॉफ

12
मुझे लगता है कि यह जवाब अस्पष्ट है और केवल सवाल से संबंधित है। (मुझे यह भी लगता है कि आपका चरित्र-चित्रण गलत है, क्योंकि यह मेरे अनुभव का खंडन करता है, लेकिन यह महत्वपूर्ण नहीं है।)
कोनराड रूडोल्फ

1
जैसा कि @KonradRudolph ने कहा, यह वास्तव में इस सवाल का जवाब नहीं देता है। प्रोलॉग जैसी भाषा लें जो आपको कुछ भी करने देती है जिसमें आप ऑपरेटर के साथ चाहते हैं, जिसमें इनफ़िक्स या प्रीफ़िक्स रखा जाने पर उनकी पूर्ववर्तीता को परिभाषित करना शामिल है। मुझे नहीं लगता है कि आप यह लिख सकते हैं कि कस्टम ऑपरेटरों को लक्षित दर्शकों के कौशल स्तर से कोई लेना-देना नहीं है, बल्कि इसलिए कि प्रोलॉग का लक्ष्य तार्किक रूप से यथासंभव पढ़ना है। कस्टम ऑपरेटरों को शामिल करने से आप उन कार्यक्रमों को लिखने की अनुमति देते हैं जो बहुत तार्किक रूप से पढ़ते हैं (सभी के बाद एक प्रोलोग कार्यक्रम सिर्फ तार्किक बयानों का एक गुच्छा है)।
डेविड काउडेन

मुझे उस स्टीवे रैंट की याद कैसे आई? ओह मैन, बुकमार्क किया गया
जॉर्ज माउर

अगर मुझे लगता है कि प्रोग्रामर सबसे अधिक कोड लिखने की संभावना रखते हैं तो क्या होगा अगर भाषाएं उन्हें यह कहने के लिए उपकरण देती हैं कि कंपाइलर को कब विभिन्न इंफ़ेक्शन बनाने चाहिए (जैसे कि एक Formatविधि के लिए ऑटो-बॉक्सिंग तर्क ) और कब मना करना चाहिए ( जैसे ऑटो-बॉक्सिंग तर्क ReferenceEquals)। अधिक क्षमता वाली भाषा प्रोग्रामर्स को यह कहने के लिए देती है कि कब कुछ इनफॉरमेशन अनुचित होगा, उतने ही सुरक्षित रूप से उपयुक्त होने पर सुविधाजनक इंफ़ॉर्मेंस दे सकते हैं।
सुपर स्टार

83

~ या "myArray.Concat (secondArray)" के साथ सरणियों के बीच चयन को देखते हुए, मैं शायद बाद वाला पसंद करूंगा। क्यों? क्योंकि ~ एक पूरी तरह से निरर्थक चरित्र है जिसका केवल इसका अर्थ है - सरणी संयोजन का - यह उस विशिष्ट परियोजना में दिया गया है जहां यह लिखा गया था।

असल में, जैसा कि आपने कहा, ऑपरेटर विधियों से अलग नहीं हैं। लेकिन जब तरीकों को पठनीय, समझ में आने वाले नाम दिए जा सकते हैं जो कोड प्रवाह की समझ में आते हैं, तो ऑपरेटर अपारदर्शी और स्थितिजन्य होते हैं।

यही कारण है कि मुझे PHP के .ऑपरेटर (स्ट्रिंग कॉन्सेप्टन) या हास्केल या ओकेमेल में अधिकांश ऑपरेटर पसंद नहीं हैं , हालांकि इस मामले में, कुछ सार्वभौमिक रूप से स्वीकृत मानक कार्यात्मक भाषाओं के लिए उभर रहे हैं।


27
वही सभी ऑपरेटरों के बारे में कहा जा सकता है। क्या उन्हें अच्छा बनाता है, और उपयोगकर्ता-परिभाषित ऑपरेटरों को भी अच्छा बना सकता है (यदि वे विवेकपूर्ण तरीके से परिभाषित किए गए हैं), यह है: उनके लिए उपयोग किए जाने वाले चरित्र के बावजूद सिर्फ एक चरित्र, व्यापक उपयोग और संभवतः mnemonic गुण स्रोत कोड में तुरंत इसका अर्थ बनाते हैं उन लोगों के लिए स्पष्ट है जो इससे परिचित हैं। तो आपका जवाब है कि यह खड़ा है कि IMHO समझाने नहीं है।

33
जैसा कि मैंने अंत में उल्लेख किया है, कुछ ऑपरेटरों की सार्वभौमिक पहचान होती है (जैसे कि मानक अंकगणितीय प्रतीकों, बिटवाइज़ शिफ़्ट, और / या, और आगे), और इसलिए उनकी मर्यादा उनकी अस्पष्टता को दूर करती है। लेकिन मनमाने ऑपरेटरों को परिभाषित करने में सक्षम होने के नाते दोनों दुनिया के सबसे खराब रखने के लिए लगता है।
अवनर शहर-काश्तन

11
तो आप भी निषेध के पक्ष में हैं, उदाहरण के लिए, भाषा के स्तर पर एकल-अक्षर के नाम? अधिक आम तौर पर, उस भाषा में कुछ भी अनुमति नहीं देता है जो अच्छे से अधिक नुकसान पहुंचाती है? यह भाषा डिजाइन के लिए एक वैध दृष्टिकोण है, लेकिन केवल एक ही नहीं है, इसलिए मुझे नहीं लगता कि आप इसे निर्धारित नहीं कर सकते।

9
मैं इस बात से सहमत नहीं हूं कि कस्टम ऑपरेटर एक सुविधा "जोड़" रहा है, यह एक प्रतिबंध को हटा रहा है। ऑपरेटर आमतौर पर केवल कार्य होते हैं, इसलिए ऑपरेटरों के लिए एक स्थिर प्रतीक तालिका के बजाय एक गतिशील, संदर्भ-निर्भर व्यक्ति का उपयोग किया जा सकता है। मुझे लगता है कि यह है कि कैसे ऑपरेटर अधिभार संभाला जाता है, क्योंकि +और <<निश्चित रूप से परिभाषित नहीं किया जाता है Object(मुझे सी + + में एक नंगे वर्ग पर ऐसा करने पर "ऑपरेटर + के लिए कोई मेल नहीं मिलता है")।
बीटगैमिट 20

10
यह पता लगाने के लिए एक लंबा समय लगता है कि कोडिंग आमतौर पर आपके लिए कुछ करने के लिए कंप्यूटर प्राप्त करने के बारे में नहीं है, यह एक दस्तावेज बनाने के बारे में है जो लोग और कंप्यूटर दोनों पढ़ सकते हैं, जिसमें लोग कंप्यूटर से काफी अधिक महत्वपूर्ण हैं। यह उत्तर बिल्कुल सही है, अगर अगले व्यक्ति (या आप 2 साल में) को 10 सेकंड भी खर्च करने पड़ते हैं तो यह पता लगाने की कोशिश करें कि इसका क्या मतलब है, आपने इसके बजाय एक विधि कॉल में टाइप करने में 10 सेकंड खर्च किए होंगे।
बिल K

71

चूंकि यह सुविधा लागू करने के लिए बहुत तुच्छ है, इसलिए यह अधिक सामान्य नहीं है?

आपका आधार गलत है। यह "लागू करने के लिए बहुत तुच्छ नहीं " है। वास्तव में, यह समस्याओं का एक बैग लाता है।

आइए पोस्ट में सुझाए गए "समाधान" पर एक नज़र डालें:

  • कोई पूर्वता नहीं । लेखक खुद कहते हैं "पूर्वता नियमों का उपयोग नहीं करना बस एक विकल्प नहीं है।"
  • शब्दार्थ जागरूक परसिंग । जैसा कि लेख कहता है, इसके लिए कंपाइलर को बहुत अधिक अर्थ ज्ञान की आवश्यकता होगी। लेख वास्तव में इसके लिए कोई समाधान प्रदान नहीं करता है और आपको बता दूं, यह केवल मामूली नहीं है। कंपाइलरों को शक्ति और जटिलता के बीच व्यापार के रूप में डिज़ाइन किया गया है। विशेष रूप से, लेखक प्रासंगिक जानकारी एकत्र करने के लिए पूर्व-पार्सिंग कदम का उल्लेख करता है, लेकिन प्री-पार्सिंग अक्षम है और पार्सिंग पासिंग को कम करने के लिए बहुत कठिन प्रयास करते हैं।
  • कोई कस्टम इनफ़िक्स ऑपरेटर नहीं । खैर, यह कोई समाधान नहीं है।
  • हाइब्रिड समाधान । यह समाधान अर्थ संबंधी जागरुकता के नुकसान के कई (लेकिन सभी नहीं) वहन करता है। विशेष रूप से, चूंकि कंपाइलर को अज्ञात टोकन का इलाज करना है, क्योंकि संभावित रूप से कस्टम ऑपरेटरों का प्रतिनिधित्व करते हुए, यह अक्सर सार्थक त्रुटि संदेश नहीं दे सकता है। पार्सिंग के साथ आगे बढ़ने के लिए उक्त ऑपरेटर की परिभाषा भी आवश्यक हो सकती है (टाइप जानकारी एकत्र करने के लिए), एक बार फिर से अतिरिक्त पार्सिंग पास की आवश्यकता होती है।

सब सब में, यह लागू करने के लिए एक महंगी विशेषता है, दोनों पार्सर जटिलता के मामले में और प्रदर्शन के मामले में, और यह स्पष्ट नहीं है कि यह बहुत सारे लाभ लाएगा। निश्चित रूप से, नए ऑपरेटरों को परिभाषित करने की क्षमता के लिए कुछ लाभ हैं, लेकिन यहां तक ​​कि वे विवादास्पद हैं (बस दूसरे उत्तरों को देखते हुए तर्क देते हैं कि नए ऑपरेटरों का होना अच्छी बात नहीं है)।


2
पवित्रता की आवाज के लिए धन्यवाद। मेरा अनुभव बताता है कि तुच्छ चीजों को खारिज करने वाले लोग या तो विशेषज्ञ हैं या आनंदपूर्वक अज्ञानी हैं, और बाद की श्रेणी में अधिक बार: x
Matthieu M.

14
इन समस्याओं में से हर एक को 20 वर्षों से मौजूद भाषाओं में हल किया गया है ...
फिलिप जेएफ

11
और फिर भी, यह असाधारण रूप से लागू करने के लिए तुच्छ है। इन सभी के बारे में भूल जाओ कि ड्रैगन बुक पार्सिंग एल्गोरिदम, यह 21 वीं सदी है और यह आगे बढ़ने का समय है। यहां तक ​​कि एक भाषा वाक्यविन्यास का विस्तार करना स्वयं आसान है, और किसी दिए गए वरीयता के ऑपरेटरों को जोड़ना तुच्छ है। हस्केल पार्सर पर एक नज़र डालें। यह "मुख्यधारा" फूला हुआ भाषाओं के लिए पार्सर की तुलना में बहुत सरल है।
एसके-लॉजिक

3
@ एसके-तर्क आपका कंबल दावा मुझे मना नहीं करता है। हां, पार्सिंग चल पड़ी है। नहीं, प्रकार के आधार पर मनमाने ढंग से संचालित करने वाले पूर्ववर्ती प्रक्रियाओं को लागू करना "तुच्छ" नहीं है। सीमित संदर्भ के साथ अच्छे त्रुटि संदेश उत्पन्न करना "तुच्छ" नहीं है। ऐसी भाषाओं के साथ कुशल पार्सर का निर्माण करना, जिन्हें बदलने के लिए कई पास की आवश्यकता होती है जो संभव नहीं है।
कोनराड रुडोल्फ

6
हास्केल में, पार्सिंग "आसान" (अधिकांश भाषाओं की तुलना में) है। वरीयता संदर्भ स्वतंत्र है। वह भाग जो आपको कठिन त्रुटि संदेश देता है, वह टाइपकाॅल और उन्नत प्रकार की प्रणाली सुविधाओं से संबंधित है, न कि उपयोगकर्ता परिभाषित ऑपरेटरों के लिए। यह ओवरलोडिंग है, उपयोगकर्ता की परिभाषा नहीं, यह कठिन समस्या है।
फिलिप जेएफ

25

आइए पल भर के लिए "पठनीयता को नुकसान पहुंचाने के तर्क" को पूरा करने के लिए "ऑपरेटरों को दुर्व्यवहार मिलता है, और भाषा के डिजाइन के निहितार्थ पर ध्यान दें।

Infix ऑपरेटरों के पास सरल पूर्ववर्ती नियमों की तुलना में अधिक मुद्दे हैं (हालांकि कुंद होने के लिए, आपके द्वारा संदर्भित लिंक उस डिज़ाइन निर्णय के प्रभाव को तुच्छ बनाता है)। एक संघर्ष संकल्प है: जब आप परिभाषित करते हैं a.operator+(b)और क्या होता है b.operator+(a)? एक दूसरे पर जिक्र करने से उस ऑपरेटर की अपेक्षित संपत्तियों को तोड़ने का काम होता है। त्रुटि को फेंकने से ऐसे मॉड्यूल बन सकते हैं जो अन्यथा एक साथ एक बार टूट जाएंगे। जब आप मिश्रण में व्युत्पन्न प्रकार फेंकना शुरू करते हैं तो क्या होता है?

इस तथ्य का तथ्य यह है कि ऑपरेटर केवल कार्य नहीं हैं। फ़ंक्शंस या तो अकेले खड़े होते हैं या उनके वर्ग के स्वामित्व में होते हैं, जो स्पष्ट पैरामीटर प्रदान करता है कि कौन सा पैरामीटर (यदि कोई हो) पॉलीमॉर्फ डिस्पैच का मालिक है।

और यह ऑपरेटरों से उत्पन्न होने वाली विभिन्न पैकेजिंग और रिज़ॉल्यूशन समस्याओं की अनदेखी करता है। कारण भाषा डिजाइनर (द्वारा और बड़ी) infix ऑपरेटर परिभाषा को सीमित करता है क्योंकि यह बहस का लाभ प्रदान करते हुए भाषा के लिए समस्याओं का ढेर बनाता है।

और स्पष्ट रूप से, क्योंकि वे लागू करने के लिए तुच्छ नहीं हैं ।


1
मेरा मानना ​​है कि यही कारण है कि जावा में उन्हें शामिल नहीं किया गया है, लेकिन उनके पास जो भाषाएं हैं, उनमें पूर्वता के स्पष्ट नियम हैं। मुझे लगता है कि यह मैट्रिक्स गुणा के समान है। यह सराहनीय नहीं है, इसलिए आपको मैट्रिस का उपयोग करते समय जागरूक होना होगा। मुझे लगता है कि कक्षाओं के साथ काम करते समय भी यही बात लागू होती है, लेकिन हां, मैं इस बात से सहमत हूं कि गैर-कम्यूटेटिव +होना बुराई है। लेकिन क्या यह वास्तव में उपयोगकर्ता-परिभाषित ऑपरेटरों के खिलाफ एक तर्क है? ऐसा लगता है कि सामान्य रूप से ऑपरेटर ओवरलोडिंग के खिलाफ एक तर्क है।
बीटगैमिट

1
@tjameson - हां, भाषाओं में गणित के लिए पूर्वता के स्पष्ट नियम हैं । गणित के संचालन के लिए पूर्ववर्ती नियम वास्तव में लागू नहीं होंगे यदि ऑपरेटर जैसी चीजों के लिए ओवरलोड हो रहे हैं boost::spirit। जैसे ही आप उपयोगकर्ता परिभाषित ऑपरेटरों को अनुमति देते हैं जो खराब हो जाते हैं क्योंकि गणित के लिए भी अच्छी तरह से परिभाषित पूर्वता के लिए कोई अच्छा तरीका नहीं है। मैंने अपने बारे में थोड़ा लिखा है कि एक भाषा के संदर्भ में जो विशेष रूप से मनमाने ढंग से परिभाषित ऑपरेटरों के साथ मुद्दों को संबोधित करने के लिए दिखता है।
तेलस्तीन

22
मैं बुलबुल को बुलाता हूं, सर। OO-ghetto के बाहर जीवन है, और वहाँ फ़ंक्शन आवश्यक रूप से किसी भी ऑब्जेक्ट से संबंधित नहीं हैं , इसलिए सही फ़ंक्शन ढूंढना ठीक ऑपरेटर को खोजने के समान है।
मथिउ एम।

1
@matthieuM। - निश्चित रूप से। स्वामित्व और प्रेषण नियम उन भाषाओं में अधिक समान हैं जो सदस्य कार्यों का समर्थन नहीं करते हैं। हालांकि, मूल सवाल यह है कि 'गैर-ओओ भाषाएं अधिक सामान्य क्यों नहीं हैं?' जो एक पूरी दूसरी बॉलगेम है।
तेलेस्टिन

11
क्या आपने देखा है कि हास्केल कस्टम ऑपरेटर कैसे करता है? वे सामान्य कार्यों की तरह ही काम करते हैं , सिवाय इसके कि उनमें एक संबद्धता भी है। (वास्तव में, यह सामान्य कार्य कर सकता है, इसलिए वहां भी वे वास्तव में भिन्न नहीं होते हैं।) मूल रूप से, ऑपरेटर डिफ़ॉल्ट रूप से infix होते हैं और नाम उपसर्ग होते हैं, लेकिन यह एकमात्र अंतर है।
तिखन जेल्विस

19

मुझे लगता है कि आपको आश्चर्य होगा कि कितनी बार ऑपरेटर ओवरलोड किसी न किसी रूप में लागू होते हैं । लेकिन वे आमतौर पर बहुत सारे समुदायों में उपयोग नहीं किए जाते हैं।

सरणी का उपयोग करने के लिए ~ का उपयोग क्यों करें? क्यों नहीं उपयोग << जैसे रूबी करता है ? क्योंकि आप जिन प्रोग्रामर के साथ काम करते हैं, वे शायद रूबी प्रोग्रामर नहीं हैं। या डी प्रोग्रामर। जब वे आपके कोड में आते हैं तो वे क्या करते हैं? उन्हें जाकर देखना होगा कि प्रतीक का क्या अर्थ है।

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

काफी उचित, आपको लगता है? यह केवल एक छोटी सी टीम थी। निजी तौर पर, मैं असहमत हूं। हर नए डेवलपर को इस शब्दावली से भ्रमित होना तय था। क्या हमें एक नया डोमेन सीखने में पर्याप्त समस्याएं नहीं हैं?

दूसरी ओर, मैं खुशी से उपयोग करेगा ऑपरेटर सी # में है क्योंकि मैं अन्य सी # डेवलपर्स उम्मीद पता है कि यह क्या है, लेकिन मैं इसे एक भाषा है कि यह डिफ़ॉल्ट रूप से समर्थन नहीं किया में ओवरलोड नहीं होता।??


मैं आपके Double.NaN उदाहरण को नहीं समझता, यह व्यवहार फ़्लोटिंग पॉइंट कल्पना का हिस्सा है और मेरे द्वारा उपयोग की जाने वाली हर भाषा में समर्थित है। क्या आप कह रहे हैं कि कस्टम ऑपरेटर समर्थित नहीं हैं क्योंकि यह उन डेवलपर्स को भ्रमित करेगा जो इस सुविधा के बारे में नहीं जानते हैं? यह टर्नररी ऑपरेटर या आपके ??उदाहरण का उपयोग करने के खिलाफ एक ही तर्क की तरह लगता है ।
बीटगैमिट

@tjameson: आप सही कह रहे हैं, वास्तव में, यह उस बिंदु पर थोड़ा सा स्पर्श था जिसे मैं बनाने की कोशिश कर रहा था, और विशेष रूप से अच्छी तरह से लिखा नहीं गया था। मैंने सोचा के ?? उदाहरण के रूप में मैं लिख रहा था कि और उस उदाहरण को पसंद करते हैं। डबल निकाल रहा है। NNN पैराग्राफ।
पीडीआर

6
मुझे लगता है कि आपका "हर नया डेवलपर इस शब्दावली से भ्रमित होने के लिए तैयार था" बिंदु थोड़ा अभाव है, अपने कोड आधार के लिए नए डेवलपर्स के सीखने की अवस्था के बारे में चिंता करना मेरे लिए उतना ही है जितना नए डेवलपर्स के सीखने की अवस्था के बारे में चिंता करना .NET का नया संस्करण। मुझे लगता है कि अधिक महत्वपूर्ण बात यह है कि जब देवता इसे सीखते हैं (नया .NET या आपका कोड आधार), तो क्या यह समझ में आता है और मूल्य दिखाता है? यदि ऐसा है, तो सीखने की अवस्था इसके लायक है, क्योंकि प्रत्येक डेवलपर को केवल इसे एक बार सीखने की आवश्यकता होती है, हालांकि कोड को अनगिनत बार प्रबंधित करने की आवश्यकता होती है, इसलिए यदि यह कोड में सुधार करता है तो यह एक मामूली लागत है।
जिमी हॉफ

7
@ जिमीहॉफ यह एक आवर्ती लागत है। हर नए डेवलपर के लिए अग्रिम भुगतान और मौजूदा डेवलपर्स को भी प्रभावित करना क्योंकि उन्हें इसका समर्थन करना है। प्रलेखन लागत और जोखिम का एक तत्व है - यह आज पर्याप्त सुरक्षित महसूस करता है, लेकिन रेखा से 30 साल नीचे, हर कोई आगे बढ़ गया होगा, भाषा और आवेदन अब "विरासत" है, प्रलेखन एक बड़ा स्टीमिंग ढेर है और कुछ गरीब चूसने वाले को प्रोग्रामर की प्रतिभा पर अपने बालों को फाड़कर छोड़ दिया जाएगा जो टाइप करने के लिए बहुत आलसी थे। "concat () "। क्या अपेक्षित मूल्य लागतों की भरपाई के लिए पर्याप्त है?
सिल्वरड्रैग

3
इसके अलावा, तर्क "हर नए डेवलपर को इस शब्दावली से भ्रमित होना तय था। क्या हमें एक नया डोमेन सीखने में पर्याप्त समस्याएं नहीं हैं?" 80 के दशक में वापस OOP के लिए लागू किया जा सकता था, उससे पहले संरचित प्रोग्रामिंग, या 10 साल पहले IoC। इस भयावह तर्क का उपयोग बंद करने का समय आ गया है।
मौरिसियो शेफ़र

11

मैं कुछ कारणों के बारे में सोच सकता हूं:

  • वे लागू करने के लिए तुच्छ नहीं हैं - मनमाने कस्टम ऑपरेटरों को अनुमति देना आपके संकलक को और अधिक जटिल बना सकता है, खासकर यदि आप उपयोगकर्ता द्वारा परिभाषित पूर्वनिर्धारणता, शुद्धता और योग्यता नियमों की अनुमति देते हैं। यदि सादगी एक गुण है, तो ऑपरेटर ओवरलोडिंग आपको अच्छी भाषा डिजाइन से दूर ले जा रहा है।
  • उनके साथ दुर्व्यवहार हो जाता है - ज्यादातर कोडर द्वारा जो यह सोचते हैं कि ऑपरेटरों को पुनर्परिभाषित करना "अच्छा" है और सभी प्रकार के कस्टम वर्गों के लिए उन्हें फिर से परिभाषित करना शुरू करें। लंबे समय से पहले, आपका कोड अनुकूलित प्रतीकों के भार से भरा हुआ है जिसे कोई और नहीं पढ़ या समझ सकता है क्योंकि ऑपरेटर पारंपरिक अच्छी तरह से समझे गए नियमों का पालन नहीं करते हैं। मैं "DSL" तर्क नहीं खरीदता, जब तक कि आपका DSL गणित का सबसेट न हो जाए :-)
  • वे पठनीयता और स्थिरता को चोट पहुँचाते हैं - यदि ऑपरेटरों को नियमित रूप से ओवरराइड किया जाता है, तो इस सुविधा का उपयोग किए जाने पर स्पॉट करना मुश्किल हो सकता है, और कोडर को लगातार खुद से पूछने के लिए मजबूर किया जाता है कि ऑपरेटर क्या कर रहा है। सार्थक फ़ंक्शन नाम देना बहुत बेहतर है। कुछ अतिरिक्त चरित्र टाइप करना सस्ता है, दीर्घकालिक रखरखाव समस्याएं महंगी हैं।
  • वे अंतर्निहित प्रदर्शन उम्मीदों को तोड़ सकते हैं । उदाहरण के लिए, मैं आमतौर पर किसी ऐरे में किसी तत्व की खोज की उम्मीद करता हूं O(1)। लेकिन ऑपरेटर ओवरलोडिंग के साथ, अनुक्रमण ऑपरेटर के कार्यान्वयन के आधार पर someobject[i]आसानी से एक O(n)ऑपरेशन हो सकता है ।

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

विचार करने के लिए कुछ दिलचस्प मामले:

  • लिस्प्स : आम तौर पर ऑपरेटरों और कार्यों के बीच बिल्कुल भी अंतर नहीं होता है - +यह सिर्फ एक नियमित कार्य है। हालांकि आप अपनी पसंद के कार्यों को परिभाषित कर सकते हैं (आमतौर पर +ऑपरेटरों के साथ अंतर्विरोध से बचने के लिए अलग नामस्थान में उन्हें परिभाषित करने का एक तरीका है )। लेकिन सार्थक फ़ंक्शन नामों का उपयोग करने के लिए एक सांस्कृतिक प्रवृत्ति है, इसलिए यह बहुत दुरुपयोग नहीं करता है। इसके अलावा, लिस्प उपसर्ग संकेतन में विशेष रूप से इस्तेमाल किया जाता है, इसलिए "सिंटैक्टिकल शुगर" में कम मूल्य होता है जो ऑपरेटर ओवरलोड प्रदान करता है।
  • जावा - ऑपरेटर के ओवरलोडिंग को रोक देता है। यह कभी-कभी कष्टप्रद होता है (कॉम्प्लेक्स नंबर केस की तरह सामान के लिए) लेकिन औसतन यह संभवतः जावा के लिए सही डिजाइन निर्णय है जो कि एक साधारण, सामान्य उद्देश्य वाले ओओपी लैंगगेज के रूप में किया जाता है। जावा कोड वास्तव में इस सादगी के परिणामस्वरूप कम / मध्यम-कुशल डेवलपर्स के लिए काफी आसान है।
  • C ++ में बहुत परिष्कृत ऑपरेटर ओवरलोडिंग है। कभी-कभी यह दुर्व्यवहार हो जाता है ( cout << "Hello World!"किसी को भी?) लेकिन दृष्टिकोण समझ में आता है सी + + की स्थिति को एक जटिल भाषा के रूप में दिया जाता है जो उच्च स्तरीय प्रोग्रामिंग को सक्षम करता है, जबकि अभी भी आपको प्रदर्शन के लिए धातु के बहुत करीब जाने की अनुमति देता है, इसलिए आप उदाहरण के लिए एक जटिल संख्या वर्ग लिख सकते हैं जो व्यवहार करता है बिल्कुल वैसा ही जैसा आप प्रदर्शन से समझौता किए बिना चाहते हैं। यह समझा जाता है कि पैर में खुद को गोली मारना आपकी खुद की जिम्मेदारी है।

8

चूंकि यह सुविधा लागू करने के लिए बहुत तुच्छ है, इसलिए यह अधिक सामान्य नहीं है?

यह लागू करने के लिए तुच्छ नहीं है (जब तक कि तुच्छ रूप से लागू नहीं किया जाता है)। यह आपको बहुत अधिक नहीं मिलता है, भले ही इसे आदर्श रूप से लागू किया गया हो: अपरिचय और अस्पष्टता से पठनीयता के नुकसान से अशांति से पठनीयता लाभ की भरपाई होती है। संक्षेप में, यह असामान्य है क्योंकि यह आमतौर पर डेवलपर्स या उपयोगकर्ताओं के समय के लायक नहीं है।

मैंने कहा, मैं ऐसा करने वाली तीन भाषाओं के बारे में सोच सकता हूं, और वे इसे विभिन्न तरीकों से करते हैं:

  • रैकेट, एक योजना, जब यह सभी एस-एक्सप्रेशन-वाई की अनुमति नहीं देता है और आपसे अपेक्षा करता है कि आप जिस भी सिंटैक्स को विस्तारित करना चाहते हैं, उसके लिए पार्सर को क्या मात्रा में लिखना है (और यह ट्रैक्टेबल बनाने के लिए उपयोगी हुक प्रदान करता है)।
  • हस्केल, एक विशुद्ध रूप से कार्य प्रोग्रामिंग भाषा है, किसी भी ऑपरेटर को परिभाषित करने की अनुमति देता है जिसमें पूरी तरह से विराम चिह्न शामिल हैं, और आपको एक नियत स्तर (10 उपलब्ध) और एक सहयोगीता प्रदान करने की अनुमति देता है। टर्नरी आदि ऑपरेटरों को बाइनरी ऑपरेटरों और उच्चतर ऑर्डर कार्यों से बनाया जा सकता है।
  • एक भरोसेमंद रूप से टाइप की गई प्रोग्रामिंग भाषा, Agda, संचालकों ( यहाँ कागज़ ) के साथ बेहद लचीली है, अगर दोनों को अनुमति देता है तो-और यदि-तब-तब उसी कार्यक्रम में परिचालकों के रूप में परिभाषित किया जाए, लेकिन इसके लेक्सर, पार्सर और मूल्यांकनकर्ता सभी दृढ़ता से प्रभावित होते हैं नतीजतन।

4
आपने कहा है कि यह "तुच्छ नहीं है", और तुरंत कुछ अपमानजनक तुच्छ कार्यान्वयन की विशेषता वाली तीन भाषाओं को सूचीबद्ध किया। तो, यह सब के बाद काफी तुच्छ है, है ना?
एसके-लॉजिक

7

कस्टम ऑपरेटरों के मुख्य कारणों में से एक को हतोत्साहित किया जाता है क्योंकि तब कोई भी ऑपरेटर कुछ भी कर सकता है / कर सकता है।

उदाहरण के लिए cstreamबहुत ज्यादा आलोचना की गई शिफ्ट ओवरलोड।

जब कोई भाषा ऑपरेटर ओवरलोड की अनुमति देती है, तो भ्रम से बचने के लिए ऑपरेटर व्यवहार को आधार व्यवहार के समान रखने के लिए आम तौर पर एक प्रोत्साहन होता है।

इसके अलावा उपयोगकर्ता परिभाषित ऑपरेटर पार्सिंग को अधिक कठिन बनाते हैं, खासकर जब कस्टम वरीयता नियम भी होते हैं।


6
मैं यह नहीं देखता कि पूरी तरह से नए ऑपरेटरों को परिभाषित करने के लिए ऑपरेटर ओवरलोडिंग के बारे में कैसे लागू होते हैं।

मैंने ऑपरेटर ओवरलोडिंग (रैखिक बीजगणित पुस्तकालयों) का बहुत अच्छा उपयोग किया है और जैसा कि आपने उल्लेख किया है, बहुत बुरा देखा है। मुझे नहीं लगता कि यह कस्टम ऑपरेटरों के खिलाफ एक अच्छा तर्क है। पार्सिंग एक मुद्दा हो सकता है, लेकिन यह बहुत स्पष्ट है जब एक ऑपरेटर की उम्मीद की जाती है। पार्स करने के बाद, ऑपरेटर अर्थ देखने के लिए कोड जनरेटर पर निर्भर है।
बीटगैमिट

3
और यह कैसे विधि अधिभार से अलग है?
जोर्ग डब्ल्यू मित्तग

@ JörgWMittag विधि अधिभार के साथ (ज्यादातर समय) एक सार्थक नाम जुड़ा हुआ है। प्रतीक के साथ यह स्पष्ट करना कठिन है कि क्या होगा
शाफ़्ट फ्रीक

1
@ratchetfreak: ठीक है। +दो चीजें जोड़ें, -उन्हें घटाएं, *उन्हें गुणा करें। मेरी भावना यह है कि कोई भी प्रोग्रामर को कार्य / विधि बनाने के लिए addवास्तव में कुछ भी जोड़ने के लिए मजबूर नहीं करता है और doNothingनक्स लॉन्च कर सकता है। और तब a.plus(b.minus(c.times(d)).times(e)बहुत कम पठनीय होता है a + (b - c * d) * e(जोड़ा बोनस - जहां पहले स्टिंग में त्रुटि है प्रतिलेखन में)। मैं यह नहीं देखता कि पहला और अधिक सार्थक कैसे होता है ...
Maciej Piechotka

4

हम उपयोगकर्ता-परिभाषित ऑपरेटरों का उपयोग नहीं करते हैं उसी कारण से हम उपयोगकर्ता-परिभाषित शब्दों का उपयोग नहीं करते हैं। कोई भी उनके कार्य को "स्वॉर्प" नहीं कहेगा। अपने विचार को दूसरे व्यक्ति तक पहुँचाने का एकमात्र तरीका साझा भाषा का उपयोग करना है। और इसका मतलब है कि शब्द और संकेत (ऑपरेटर) दोनों को उस समाज के लिए जाना जाना चाहिए, जिसके लिए आप अपना कोड लिख रहे हैं।

इसलिए आप जिन प्रोग्रामिंग भाषाओं में उपयोग करते हैं, वे वे ऑपरेटर हैं जिन्हें हम स्कूल (अंकगणित) में पढ़ाया गया है या वे जिन्हें प्रोग्रामिंग समुदाय में स्थापित किया गया है, जैसे बूलियन ऑपरेटर।


1
कि एक समारोह के पीछे अर्थ खोजने की क्षमता जोड़ें। "स्वॉर्प" के मामले में आप इसे आसानी से एक खोज बॉक्स में चिपका सकते हैं और पा सकते हैं कि यह दस्तावेज है। एक खोज इंजन में एक ऑपरेटर को चिपकाना एक पूरी तरह से अलग गेंद पार्क है। हमारे वर्तमान खोज इंजन केवल ऑपरेटरों को खोजने में चूसना करते हैं, और मैंने कुछ मामलों में अर्थ खोजने की कोशिश में बहुत समय बर्बाद किया है।
मार्क एच

1
आप कितना "स्कूल" गिनते हैं? उदाहरण के लिए, मुझे लगता है कि ∈ के लिए elemएक महान विचार है और निश्चित रूप से एक ऑपरेटर को हर किसी को समझना चाहिए, लेकिन अन्य असहमत लगते हैं।
तिखन जेल्विस

1
यह प्रतीक के साथ समस्या नहीं है। यह कीबोर्ड की समस्या है। मैं उदाहरण के लिए यूनिकोड ब्यूटिफायर इनेबल्ड के साथ एमएसीएस हैसेल-मोड का उपयोग करता हूं। और यह स्वचालित रूप से यूसीआई ऑपरेटरों को यूनिकोड प्रतीकों में परिवर्तित करता है। लेकिन मैं इसे टाइप नहीं कर पाऊंगा अगर एक एसिसी के बराबर नहीं होगा।
वागीफ वर्डी

2
प्राकृतिक भाषाएं केवल "उपयोगकर्ता द्वारा परिभाषित शब्द" से निर्मित होती हैं और कुछ नहीं। और कुछ भाषाएँ वास्तव में कस्टम शब्द बनाने को प्रोत्साहित करती हैं।
एसके-लॉजिक

4

जैसा कि ऐसी भाषाएं जो इस तरह के ओवरलोडिंग का समर्थन करती हैं: स्काला वास्तव में, बहुत क्लीनर और बेहतर तरीके से C ++ कर सकती है। अधिकांश वर्णों का उपयोग फ़ंक्शन नामों में किया जा सकता है, इसलिए यदि आप चाहें तो आप ऑपरेटरों को परिभाषित कर सकते हैं! + * = ++, जैसे। इनफ़िक्स के लिए अंतर्निहित समर्थन है (सभी कार्यों के लिए एक तर्क)। मुझे लगता है कि आप इस तरह के कार्यों की संबद्धता को भी परिभाषित कर सकते हैं। हालाँकि, आप पूर्वता को परिभाषित नहीं कर सकते (केवल बदसूरत चाल के साथ, यहाँ देखें )।


4

एक बात जिसका उल्लेख अभी तक नहीं किया गया है वह है स्मॉलटाक का मामला, जहां सब कुछ (ऑपरेटरों सहित) एक संदेश भेजना है। "ऑपरेटर्स" जैसे +, |और इसी तरह वास्तव में एकात्मक तरीके हैं।

सभी विधियों को ओवरराइड किया जा सकता है, तो a + bइसका मतलब है कि पूर्णांक जोड़ अगर aऔर bदोनों पूर्णांक हैं, और इसका मतलब वेक्टर जोड़ है यदि वे दोनों हैं OrderedCollection

कोई पूर्ववर्ती नियम नहीं हैं, क्योंकि ये केवल विधि कॉल हैं। इसका मानक गणितीय अंकन के लिए एक महत्वपूर्ण निहितार्थ है: 3 + 4 * 5इसका मतलब है (3 + 4) * 5, नहीं 3 + (4 * 5)

(यह स्मॉलटाक न्यूबिक्स के लिए एक प्रमुख ठोकर है। गणित के नियमों को तोड़ना एक विशेष मामले को हटा देता है, जिससे सभी कोड मूल्यांकन समान रूप से दाएं से बाएं हो जाते हैं, जिससे भाषा बहुत सरल हो जाती है।)


3

आप यहां दो चीजों के खिलाफ लड़ रहे हैं:

  1. पहले स्थान पर भाषा में ऑपरेटर क्यों मौजूद हैं?
  2. कार्यों / विधियों पर ऑपरेटरों का गुण क्या है?

अधिकांश भाषाओं में, ऑपरेटरों को वास्तव में सरल कार्यों के रूप में लागू नहीं किया जाता है। उनके पास कुछ फ़ंक्शन मचान हो सकते हैं, लेकिन संकलक / रनटाइम स्पष्ट रूप से उनके अर्थ अर्थ और मशीन कोड में उन्हें कुशलतापूर्वक अनुवाद करने के बारे में पता है। यह बिल्ट-इन फ़ंक्शंस की तुलना में बहुत अधिक सच है (यही वजह है कि अधिकांश कार्यान्वयन भी उनके कार्यान्वयन में सभी फ़ंक्शन कॉल ओवरहेड को शामिल नहीं करते हैं)। अधिकांश ऑपरेटर सीपीयू में पाए जाने वाले आदिम निर्देशों पर उच्च स्तर के अमूर्त हैं (जो कि आंशिक रूप से अधिकांश ऑपरेटर अंकगणितीय, बूलियन या बिटवाइज़ हैं)। आप उन्हें "विशेष" फ़ंक्शंस के रूप में मॉडल कर सकते हैं (उन्हें "प्रिमिटिव्स" या "बिल्डिंस" या "नेटिव" या जो भी कह सकते हैं), लेकिन ऐसा करने के लिए इस तरह के विशेष फ़ंक्शंस को परिभाषित करने के लिए मूल रूप से शब्दार्थ के बहुत मजबूत सेट की आवश्यकता होती है। वैकल्पिक रूप से बिल्ट-इन ऑपरेटर होते हैं जो शब्दार्थ रूप से उपयोगकर्ता परिभाषित ऑपरेटरों की तरह दिखते हैं, लेकिन जो अन्यथा संकलक में विशेष पथ का आह्वान करते हैं। यह दूसरे प्रश्न के उत्तर के लिए चलता है ...

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

C ++ के ऑपरेटर अधिभार इस की जांच के लिए उपजाऊ जमीन प्रदान करते हैं। अधिकांश ऑपरेटर ओवरलोड "दुरुपयोग" ओवरलोड के रूप में आता है जो कि कुछ शब्दार्थ अनुबंध को तोड़ता है जिसे मोटे तौर पर समझा जाता है (एक क्लासिक उदाहरण ऑपरेटर का एक अधिभार है + जैसे कि + b! = B + a, या जहां + इसके किसी भी प्रकार को संशोधित करता है) ऑपरेंड)।

यदि आप Smalltalk को देखते हैं, जो ऑपरेटर को ओवरलोडिंग और उपयोगकर्ता परिभाषित ऑपरेटरों की अनुमति देता है , तो आप देख सकते हैं कि कोई भाषा इसे करने के बारे में कैसे जा सकती है, और यह कितना उपयोगी होगा। स्मॉलटाकल में, ऑपरेटर केवल अलग-अलग सिंटैक्टिकल गुणों के साथ विधियां हैं (अर्थात्, वे इन्फिक्स बाइनरी के रूप में एन्कोडेड हैं)। भाषा विशेष त्वरित ऑपरेटरों और विधियों के लिए "आदिम तरीकों" का उपयोग करती है। आप पाते हैं कि यदि कोई भी उपयोगकर्ता परिभाषित ऑपरेटर बनाया जाता है, और जब वे होते हैं, तो वे उतना उपयोग नहीं करते हैं जितना कि लेखक संभवतः उनके लिए उपयोग करने का इरादा रखता है। यहां तक ​​कि एक ऑपरेटर ओवरलोड के बराबर भी दुर्लभ है, क्योंकि यह एक विधि के बजाय एक ऑपरेटर के रूप में एक नए फ़ंक्शन को परिभाषित करने के लिए ज्यादातर शुद्ध नुकसान है, क्योंकि उत्तरार्द्ध फ़ंक्शन के शब्दार्थ की अभिव्यक्ति के लिए अनुमति देता है।


1

मैंने हमेशा सी ++ में ऑपरेटर ओवरलोड पाया है जो एक एकल-डेवलपर टीम के लिए एक सुविधाजनक शॉर्टकट है, लेकिन जो लंबी अवधि में सभी प्रकार के भ्रम का कारण बनता है, क्योंकि विधि कॉल "आसान" तरीके से हो रही है जो आसान नहीं है doxygen जैसे उपकरणों को अलग करने के लिए, और लोगों को सही तरीके से उपयोग करने के लिए मुहावरों को समझने की आवश्यकता है।

कभी-कभी यह बहुत कठिन होता है कि आप जो अपेक्षा करते हैं, उससे भी अधिक कठिन है। एक बार, एक बड़े क्रॉस-प्लेटफ़ॉर्म C ++ प्रोजेक्ट में मैंने फैसला किया कि जिस तरह से एक FilePathऑब्जेक्ट (जावा के Fileऑब्जेक्ट के समान ) बनाकर रास्ते को सामान्य बनाने के लिए यह एक अच्छा विचार होगा, जिसमें ऑपरेटर होगा / एक दूसरे को अवगत कराने के लिए उपयोग किया जाएगा उस पर पथ भाग (ताकि आप ऐसा कुछ कर सकें File::getHomeDir()/"foo"/"bar"और यह हमारे सभी समर्थित प्लेटफार्मों पर सही काम करेगा)। हर कोई जो इसे देखता था, वह अनिवार्य रूप से कहता था, "व्हाट द हेल? स्ट्रिंग डिवीजन? ... ओह, यह प्यारा है, लेकिन मैं इसे सही काम करने के लिए भरोसा नहीं करता।"

इसी तरह, ग्राफिक्स प्रोग्रामिंग या अन्य क्षेत्रों में बहुत सारे मामले हैं जहां वेक्टर / मैट्रिक्स गणित बहुत कुछ होता है जहां यह मैट्रिक्स * मैट्रिक्स, वेक्टर * वेक्टर (डॉट), वेक्टर% वेक्टर (क्रॉस), मैट्रिक्स * वेक्टर (जैसे चीजें करने के लिए लुभाता है) मैट्रिक्स परिवर्तन), मैट्रिक्स ^ वेक्टर (विशेष मामले मैट्रिक्स समरूप समन्वय की अनदेखी - सतह मानदंडों के लिए उपयोगी), और इसी तरह, लेकिन जब यह वेक्टर गणित पुस्तकालय लिखने वाले व्यक्ति के लिए थोड़ा समय बचाता है, तो यह केवल समाप्त होता है दूसरों के लिए इस मुद्दे को और अधिक भ्रमित करना। यह सिर्फ इसके लायक नहीं है।


0

ऑपरेटर अधिभार एक ही कारण के लिए एक बुरा विचार है कि विधि अधिभार एक बुरा विचार है: स्क्रीन पर एक ही प्रतीक के अलग-अलग अर्थ होंगे जो इसके आसपास है। यह आकस्मिक पढ़ने के लिए और अधिक कठिन बना देता है।

चूंकि पठनीयता बनाए रखने का एक महत्वपूर्ण पहलू है, इसलिए आपको हमेशा ओवरलोडिंग (कुछ विशेष मामलों को छोड़कर) से बचना चाहिए। यह प्रत्येक प्रतीक (चाहे ऑपरेटर या अल्फ़ान्यूमेरिक आइडेंटिफ़ायर) के लिए कहीं बेहतर है कि इसका एक अनूठा अर्थ है जो अपने आप खड़ा हो।

उदाहरण के लिए: अपरिचित कोड पढ़ते समय, यदि आप एक नए अल्फ़ान्यूम पहचानकर्ता का सामना करते हैं, जिसे आप नहीं जानते हैं, तो कम से कम आपको यह फायदा होगा कि आप जानते हैं कि आप इसे नहीं जानते हैं। फिर आप इसे देख सकते हैं। यदि, हालांकि, आप एक सामान्य पहचानकर्ता या ऑपरेटर देखते हैं जिसका अर्थ आप जानते हैं, तो आपको यह ध्यान देने की संभावना कम है कि यह वास्तव में पूरी तरह से अलग अर्थ रखने के लिए अतिभारित है। यह जानने के लिए कि क्या ऑपरेटरों को ओवरलोड किया गया है (एक कोड बेस में, जो ओवरलोडिंग का व्यापक उपयोग करता है), आपको पूर्ण कोड के एक कार्यशील ज्ञान की आवश्यकता होगी, भले ही आप केवल इसका एक छोटा सा हिस्सा पढ़ना चाहते हों। इससे नए डेवलपर्स को उस कोड पर गति लाने में मुश्किल होगी, और लोगों को छोटी नौकरी के लिए लाना असंभव होगा। यह प्रोग्रामर जॉब सिक्योरिटी के लिए अच्छा हो सकता है, लेकिन अगर आप कोड बेस की सफलता के लिए जिम्मेदार हैं, तो आपको इस अभ्यास से हर कीमत पर बचना चाहिए।

क्योंकि ऑपरेटर आकार में छोटे होते हैं, इसलिए ओवरलोडिंग ऑपरेटर अधिक घने कोड की अनुमति देते हैं, लेकिन कोड को घना बनाना वास्तविक लाभ नहीं है। दो बार तर्क के साथ एक पंक्ति पढ़ने के लिए दो बार लगती है। संकलक परवाह नहीं करता है। एकमात्र मुद्दा मानवीय पठनीयता है। चूंकि कोड कॉम्पैक्ट बनाने से पठनीयता में वृद्धि नहीं होती है, इसलिए कॉम्पैक्टनेस के लिए कोई वास्तविक लाभ नहीं है। आगे बढ़ो और अंतरिक्ष ले लो, और अद्वितीय संचालन को एक अद्वितीय पहचानकर्ता दें, और आपका कोड लंबे समय में अधिक सफल होगा।


"स्क्रीन पर एक ही प्रतीक के अलग-अलग अर्थ होंगे जो उसके आस-पास के आधार पर होता है" - यह ज्यादातर भाषाओं में कई ऑपरेटरों के लिए पहले से ही मामला है।
rkj

-1

पूर्वगामी और जटिल पार्सिंग को अलग करने के लिए तकनीकी कठिनाइयाँ, मुझे लगता है कि प्रोग्रामिंग भाषा क्या है, इसके कुछ पहलुओं पर विचार करना होगा।

ऑपरेटर्स आमतौर पर लघु तार्किक निर्माण होते हैं जिन्हें मुख्य भाषा में अच्छी तरह से परिभाषित और प्रलेखित किया जाता है (तुलना, असाइन ..)। वे भी आमतौर पर प्रलेखन के बिना समझने के लिए (तुलना मुश्किल है a^bके साथ xor(a,b)उदाहरण के लिए)। ऑपरेटरों की एक सीमित संख्या है जो वास्तव में सामान्य प्रोग्रामिंग (>, <, =, + आदि) में समझ में आ सकती है।

मेरा विचार यह है कि किसी भाषा में अच्छी तरह से परिभाषित ऑपरेटरों के एक सेट से चिपके रहना बेहतर है - फिर ऑपरेटर को उन ऑपरेटरों को ओवरलोड करने की अनुमति दें (एक नरम सिफारिश दी जाती है कि ऑपरेटरों को एक ही काम करना चाहिए, लेकिन एक कस्टम डेटा प्रकार के साथ)।

आपके उपयोग के मामले ~और |वास्तव में सरल ऑपरेटर ओवरलोडिंग (सी #, सी ++, आदि) के साथ संभव होंगे। डीएसएल एक वैध उपयोग क्षेत्र है, लेकिन शायद एकमात्र वैध क्षेत्रों में से एक है (मेरे दृष्टिकोण से)। हालाँकि, मुझे लगता है कि नई भाषाओं को बनाने के लिए बेहतर उपकरण हैं। किसी अन्य कंपाइलर-कंपाइलर टूल का उपयोग करके किसी अन्य भाषा के भीतर एक सच्ची डीएसएल भाषा को निष्पादित करना उतना मुश्किल नहीं है। वही "विस्तार LUA तर्क" के लिए जाता है। एक भाषा को मुख्य रूप से एक विशिष्ट तरीके से समस्याओं को हल करने के लिए मुख्य रूप से परिभाषित किया जाता है, उप-भाषाओं के लिए नींव नहीं होना चाहिए (अपवाद मौजूद है)।


-1

इसके लिए एक और कारक यह है कि उपलब्ध ऑपरेटरों के साथ एक ऑपरेशन को परिभाषित करने के लिए यह हमेशा आगे नहीं होता है। मेरा मतलब है, हां, किसी भी प्रकार की संख्या के लिए, '*' ऑपरेटर समझदारी बना सकता है, और आमतौर पर भाषा में या मौजूदा मॉड्यूल में लागू किया जाता है। लेकिन विशिष्ट जटिल वर्गों के मामले में, जिन्हें आपको परिभाषित करने की आवश्यकता है (शिपइंगएड्रेस, विंडो मैनजर, ​​ऑब्जेक्शन, प्लेयरचैचर, आदि जैसी चीजें) जो व्यवहार स्पष्ट नहीं है ... किसी पते पर संख्या जोड़ने या घटाने का क्या मतलब है? दो पते गुणा करें?

निश्चित रूप से, आप यह परिभाषित कर सकते हैं कि एक नौवहन को जोड़ने के लिए एकAddress क्लास का अर्थ है एक कस्टम ऑपरेशन जैसे "पता में पंक्ति 1 को बदलें" ("setLine1" फ़ंक्शन के बजाय) और एक संख्या जोड़ने से "ज़िप कोड बदलें" ("setZinCode" के बजाय) , लेकिन तब कोड बहुत पठनीय और भ्रमित करने वाला नहीं है। हम आम तौर पर सोचते हैं कि ऑपरेटर का उपयोग बुनियादी प्रकार / वर्गों में किया जाता है, क्योंकि उनका व्यवहार सहज, स्पष्ट और सुसंगत है (एक बार जब आप भाषा से परिचित होते हैं, तो कम से कम)। Integer, String, ComplexNumbers इत्यादि प्रकारों में सोचें।

इसलिए, भले ही परिभाषित करने वाले ऑपरेटर कुछ विशिष्ट मामलों में बहुत उपयोगी हो सकते हैं, उनका वास्तविक-विश्व कार्यान्वयन काफी सीमित है, क्योंकि 99% मामले जहां एक स्पष्ट जीत होगी, वे पहले से ही मूल भाषा पैकेज में लागू होते हैं।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.