गो में कोई जेनरिक क्यों नहीं?


126

डिस्क्लेमर: मैंने केवल एक दिन के लिए गो के साथ खेला है, इसलिए एक अच्छा मौका है जो मैंने बहुत याद किया है।

क्या कोई जानता है कि गो में जेनरिक / टेम्प्लेट / व्हाट्सएपनाम का कोई वास्तविक समर्थन क्यों नहीं है? तो एक सामान्य है map, लेकिन यह संकलक द्वारा आपूर्ति की जाती है, जबकि एक गो प्रोग्रामर अपना स्वयं का कार्यान्वयन नहीं लिख सकता है। गो के रूप में संभव के रूप में ऑर्थोगोनल बनाने के बारे में सभी चर्चा के साथ, मैं एक सामान्य प्रकार का उपयोग क्यों कर सकता हूं लेकिन एक नया निर्माण नहीं कर सकता हूं?

विशेष रूप से जब यह कार्यात्मक प्रोग्रामिंग की बात आती है, तो लैम्ब्डा होते हैं, यहां तक ​​कि बंद भी होते हैं, लेकिन एक स्थिर प्रकार की प्रणाली में जेनेरिक की कमी होती है, मैं कैसे लिखूं, ठीक है, सामान्य उच्च क्रम के कार्य जैसे filter(predicate, list)? ओके, लिंक्ड लिस्ट और interface{}लाइक को टाइप सेफ्टी के साथ किया जा सकता है ।

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


मुझे लगता है कि यह इंगित करने लायक है: इंटरफ़ेस {} का उपयोग करने से प्रकार की सुरक्षा का त्याग नहीं होता है। यह एक प्रकार है, और अन्य प्रकारों के लिए मुखर (कास्ट नहीं) किया जा सकता है, लेकिन ये दावे अभी भी टाइप सुरक्षा को बनाए रखने के लिए रनटाइम चेक करते हैं।
cthom06

12
interface{}बलिदान स्थिर प्रकार की सुरक्षा। हालाँकि, यह कुछ अजीब शिकायत है जब स्कीम का उल्लेख करना अगला पैराग्राफ है, क्योंकि स्कीम में आमतौर पर स्थैतिक प्रकार की जाँच नहीं होती है।
पूल

@ मापी: मैं जिस चीज से चिंतित हूं वह एक भाषा के भीतर एक प्रतिमान से चिपकी हुई है। या तो मैं स्थैतिक प्रकार की सुरक्षा का उपयोग कर रहा हूं XOR नहीं।

2
btw यह 'गो' वर्तनी है, 'गो' नहीं, जैसा कि आप golang.org पर देख सकते हैं। और यह केस-संवेदी है। :-)
पूलि जूल

1
कैसे github.com/facebookgo/generics के बारे में ?
आइलिमिस्ट

जवाबों:


78

यह उत्तर आपको यहां मिलेगा: http://golang.org/doc/faq#generics

गो के पास सामान्य प्रकार क्यों नहीं हैं?

कुछ बिंदुओं पर पीढ़ी को अच्छी तरह से जोड़ा जा सकता है। हम उनके लिए एक तात्कालिकता महसूस नहीं करते हैं, हालांकि हम समझते हैं कि कुछ प्रोग्रामर करते हैं।

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

यह एक खुला मुद्दा बना हुआ है।


14
@amoebe, "खाली इंटरफ़ेस", वर्तनी interface{}, सबसे बुनियादी इंटरफ़ेस प्रकार है, और प्रत्येक ऑब्जेक्ट इसे प्रदान करता है। यदि आप उन्हें पकड़े हुए एक कंटेनर बनाते हैं, तो यह किसी भी (गैर-आदिम) वस्तु को स्वीकार कर सकता है। तो यह Objectsजावा में एक कंटेनर पकड़े के समान है ।
पूल जू

4
@YinWang जेनरिक एक प्रकार के वातावरण में सरल नहीं हैं। अधिक महत्वपूर्ण बात; इंटरफ़ेस {} सी में शून्य * पॉइंटर्स के बराबर नहीं है। बेहतर उपमाएँ C # की System.Object या Objective-C की आईडी प्रकार होंगी। टाइप जानकारी संरक्षित है और "कास्ट" (वास्तव में) को अपने ठोस प्रकार पर वापस रखा जा सकता है। : यहाँ किरकिरा विवरण प्राप्त करें golang.org/ref/spec#Type_assertions
tbone

2
@tbone C # 'System.Object (या जावा का ऑब्जेक्ट प्रति se) मूल रूप से "सी के शून्य पॉइंटर्स" से मेरा तात्पर्य है (उस भाग को अनदेखा करना जो आप उन भाषाओं में सूचक अंकगणित नहीं कर सकते हैं)। वे हैं जहाँ स्थैतिक प्रकार की जानकारी खो जाती है। एक कलाकार ज्यादा मदद नहीं करेगा क्योंकि आपको एक रनटाइम त्रुटि मिलेगी।
इयान

1
@ChristopherPfohl D के टेम्पलेट्स का संकलन समय उपरिव्यय की तुलना में काफी कम है, और आम तौर पर आप खाके से अधिक कोड उत्पन्न नहीं करते हैं क्योंकि आप सामान्य रूप से अन्यथा करते हैं (आप वास्तव में परिस्थितियों के आधार पर कम कोड के साथ समाप्त हो सकते हैं )।
घन

3
@ChristopherPfohl मुझे लगता है कि केवल जावा जेनेरिक में ही आदिम प्रकारों के लिए बॉक्सिंग / अनबॉक्सिंग मुद्दा है? C # के पुनरीक्षित जेनेरिक में समस्या नहीं है।
ca9163d9

32

जाना २

Https://blog.golang.org/go2draft पर जेनरिक के लिए ड्राफ्ट डिज़ाइन है ।

जाओ १

गो दिग्गजों में से एक, रस कॉक्स ने द जेनेरिक दुलेमा नामक एक ब्लॉग पोस्ट लिखा , जिसमें उन्होंने पूछा

... क्या आप धीमी प्रोग्रामर, धीमी संकलक और फूला हुआ बायनेरी, या धीमी निष्पादन समय चाहते हैं?

धीमी प्रोग्रामर बिना जेनरिक के परिणाम के होते हैं, धीमे संकलक C ++ की तरह जेनेरिक और स्लो एक्जीक्यूटिव टाइम स्टेम बॉक्सिंग-अनबॉक्सिंग दृष्टिकोण से उत्पन्न होते हैं जो जावा उपयोग करता है।

चौथी संभावना ब्लॉग में उल्लेख नहीं किया जा रहा है C # मार्ग। सी ++ में विशेष कोड उत्पन्न करना, लेकिन जब जरूरत हो तब रनटाइम पर। मैं वास्तव में इसे पसंद करता हूं, लेकिन गो # के विपरीत है, इसलिए यह संभवतः लागू नहीं है ...

मुझे लगता है कि लोकप्रिय जावा 1.4 की तकनीक की तरह उपयोग करते हुए उल्लेख करना चाहिए बार में सामान्य प्रोग्रामिंग कि करने के लिए डाले interface{}बिल्कुल के रूप में एक ही समस्याओं से ग्रस्त बॉक्सिंग-unboxing, संकलन समय प्रकार सुरक्षा के नुकसान के अलावा (क्योंकि है कि हम क्या कर रहे है)। छोटे प्रकारों (जैसे ints) के लिए Go interface{}प्रकार का अनुकूलन करता है ताकि इंटरफ़ेस में डाले गए ints की एक सूची {} स्मृति के एक समीपवर्ती क्षेत्र पर कब्जा कर ले और सामान्य ints के रूप में केवल दो बार ज्यादा जगह ले। हालांकि, अभी भी कास्टिंग चेक के ओवरहेड है interface{}, हालांकि। संदर्भ

सभी प्रोजेक्ट जो जाने के लिए सामान्य समर्थन को जोड़ते हैं (उनमें से कई हैं और सभी दिलचस्प हैं) समान रूप से संकलन कोड कोड पीढ़ी के सी ++ मार्ग पर जाते हैं।


इस दुविधा का मेरा समाधान कार्यक्रम को प्रोफ़ाइल करने के विकल्प के साथ "धीमी निष्पादन समय" के लिए डिफ़ॉल्ट रूप से जाना होगा और "धीमी कंपाइलर और फूला हुआ बायनेरिज़" मोड में सबसे अधिक प्रदर्शन संवेदनशील भागों को फिर से जोड़ना होगा। बहुत बुरा है कि लोग वास्तव में उस तरह के सामान को लागू करते हैं जो सी ++ मार्ग लेते हैं।
13:76 पर user7610

1
यह उल्लेख किया गया था कि छोटे प्रकार (यानी इंट) को []interface{}2x रैम के रूप में उपयोग किया जाता है []int। जबकि सच है, यहां तक ​​कि छोटे प्रकार (जैसे बाइट) 16x तक रैम का उपयोग करते हैं []byte
बीएमपीएन

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

दुविधा यह है कि किस दृष्टिकोण को चुना जाए। यदि आप C ++ दृष्टिकोण पर जाकर दुविधा का समाधान करते हैं, तो दुविधा हल हो जाती है।
user7610

9

भले ही वर्तमान में जेनरिक बिल्ट-इन नहीं हैं, लेकिन जाने के लिए जेनरिक के कई बाहरी कार्यान्वयन हैं, जो कोड का निर्माण करने वाली छोटी उपयोगिताओं के साथ संयोजन में टिप्पणियों का उपयोग करते हैं।

यहाँ इस तरह के एक कार्यान्वयन है: http://clipperhouse.github.io/gen/


1

दरअसल, इस पोस्ट के अनुसार :

कई लोगों ने (गलत तरीके से) निष्कर्ष निकाला है कि गो टीम की स्थिति यह है कि "गो के पास कभी जेनेरिक नहीं होगा।" इसके विपरीत, हम समझते हैं कि संभावित जेनरिक में गो को अधिक लचीला और शक्तिशाली बनाने के लिए और गो को अधिक जटिल बनाने के लिए दोनों हैं। अगर हम जेनरिक को जोड़ना चाहते हैं, तो हम इसे इस तरह से करना चाहते हैं, जिसमें जितना संभव हो उतना कम जटिलता के साथ लचीलापन और शक्ति मिलती है।


-1

पैरामीट्रिक बहुरूपता (जेनरिक) है के लिए विचार किया जा रहा जाओ 2

यह दृष्टिकोण एक अनुबंध की अवधारणा को पेश करेगा , जिसका उपयोग प्रकार मापदंडों पर बाधाओं को व्यक्त करने के लिए किया जा सकता है:

contract Addable(a T) {
  a + a // Could be += also
}

इस तरह के अनुबंध का उपयोग तब किया जा सकता है:

func Sum(type T Addable)(l []T) (total T) {
  for _, e := range l {
    total += e
  }
  return total
}

यह इस स्तर पर एक प्रस्ताव है


आपका filter(predicate, list)कार्य इस प्रकार के पैरामीटर के साथ कार्यान्वित किया जा सकता है:

func Filter(type T)(f func(T) bool, l []T) (result []T) {
  for _, e := range l {
    if f(e) {
      result = append(result, e)
    }
  }
  return result
}

इस मामले में, विवश होने की आवश्यकता नहीं है T


1
यदि आप आज इस उत्तर को पढ़ रहे हैं, तो ध्यान रखें कि अनुबंध प्रस्ताव के मसौदे से हटा दिए गए हैं: go.googlesource.com/proposal/+/refs/heads/master/design/…
jub0bs
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.