क्या विषम सूचियों का कोई विशिष्ट उद्देश्य है?


13

C # और Java बैकग्राउंड से आने के कारण, मुझे अपनी सूचियों के प्रति सजातीय होने की आदत है, और इससे मुझे समझ में आता है। जब मैंने लिस्प को चुनना शुरू किया, तो मैंने देखा कि सूचियां विषम हो सकती हैं। जब मैंने dynamicC # में कीवर्ड के साथ चारों ओर पेंच करना शुरू किया , तो मैंने देखा कि, C # 4.0 के रूप में, विषम सूची भी हो सकती है:

List<dynamic> heterogeneousList

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


1
क्या आपका मतलब था ... मैंने देखा कि सूचियां विषम हो सकती हैं ...?
वर्ल्ड इंजीनियर

List<dynamic>बस करने से अलग (आपके सवाल के लिए) कैसे है List<object>?
पीटर के।

@WorldEngineer हाँ, मैं करता हूँ। मैंने अपनी पोस्ट अपडेट कर दी है। धन्यवाद!
जेटी

@PeterK। मुझे लगता है कि हर रोज इस्तेमाल के लिए कोई अंतर नहीं है। हालाँकि, C # में प्रत्येक प्रकार System.Object से प्राप्त नहीं होता है, इसलिए वहाँ किनारे मामले होंगे जहाँ मतभेद हैं।
जेटी

जवाबों:


16

कागज जोरदार heterogenous संग्रह टाइप ओलेग Kiselyov द्वारा, राल्फ Lämmel, और Keean Schupke न केवल हास्केल में heterogenous सूचियों के एक कार्यान्वयन, लेकिन यह भी जब, क्यों और कैसे आप HLists का प्रयोग करेंगे की एक प्रेरित उदाहरण में शामिल है। विशेष रूप से, वे इसका उपयोग टाइप-सेफ कंपाइल-टाइम चेक डेटाबेस एक्सेस के लिए कर रहे हैं। (लगता है कि LINQ, वास्तव में, कागज वे संदर्भित कर रहे हैं है इरिक मेजर एट अल कि LINQ करने के लिए नेतृत्व द्वारा हास्केल कागज।)

HLists पेपर के परिचयात्मक पैराग्राफ से उद्धरण:

यहां उन विशिष्ट उदाहरणों की एक ओपन-एंडेड सूची दी गई है जो विषम संग्रहों के लिए कॉल करते हैं:

  • एक प्रतीक तालिका जो विभिन्न प्रकार की प्रविष्टियों को संग्रहीत करने वाली है, वह विषम है। यह एक परिमित मानचित्र है, जहाँ परिणाम प्रकार तर्क मान पर निर्भर करता है।
  • एक XML तत्व विषम टाइप किया जाता है। वास्तव में, XML तत्व नेस्टेड संग्रह हैं जो नियमित अभिव्यक्तियों और 1-अस्पष्ट संपत्ति द्वारा विवश हैं।
  • SQL क्वेरी द्वारा दी गई प्रत्येक पंक्ति स्तंभ नामों से कोशिकाओं तक एक विषम नक्शा है। क्वेरी का परिणाम विषम पंक्तियों की एक सजातीय धारा है।
  • एक कार्यात्मक भाषा में एक उन्नत ऑब्जेक्ट सिस्टम को जोड़ने के लिए एक तरह के विषम संग्रह की आवश्यकता होती है जो उप-रिकॉर्ड और एक गणना इंटरफ़ेस के साथ एक्स्टेंसिबल रिकॉर्ड को जोड़ती है।

ध्यान दें कि आपने अपने प्रश्न में जो उदाहरण दिए हैं, वे वास्तव में इस अर्थ में सूचीबद्ध नहीं हैं कि इस शब्द का आमतौर पर उपयोग किया जाता है। वे कमजोर रूप से टाइप किए गए या अप्रकाशित सूचियाँ हैं। वास्तव में, वे वास्तव में समरूप सूची हैं, क्योंकि सभी तत्व एक ही प्रकार के हैं: objectया dynamic। फिर आपको instanceofवास्तव में तत्वों के साथ सार्थक रूप से काम करने में सक्षम बनाने के लिए, जाति या अनियंत्रित परीक्षण या ऐसा कुछ करने के लिए मजबूर किया जाता है , जो उन्हें कमजोर रूप से टाइप करता है।


लिंक और आपकी प्रतिक्रिया के लिए धन्यवाद। आप एक अच्छा बिंदु बनाते हैं कि सूचियां वास्तव में विषम नहीं हैं लेकिन कमजोर टाइप की हैं। मैं उस कागज़ को पढ़ने के लिए उत्सुक हूँ (शायद कल, मुझे आज रात मिल गया :))
Jetti

5

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

एक गतिशील रूप से टाइप की गई भाषा में, सजातीय कंटेनरों में वास्तव में विषम लोगों की तुलना में एक मामूली ओवरहेड होगा, क्योंकि जोड़े गए सभी तत्वों को टाइप-चेक करना होगा।

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


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

@ जेटी: कहो कि आपके पास विभिन्न प्रकार के उपयोगकर्ता-दर्ज सेटिंग्स की सूची है। आप एक इंटरफ़ेस बना सकते हैं IUserSettingऔर इसे कई बार लागू कर सकते हैं , या एक सामान्य बना सकते हैं UserSetting<T>, लेकिन स्थैतिक टाइपिंग के साथ समस्याओं में से एक यह है कि आप इंटरफ़ेस को परिभाषित कर रहे हैं इससे पहले कि आपको पता चले कि यह कैसे उपयोग किया जा रहा है। पूर्णांक सेटिंग्स के साथ आप जो चीजें करते हैं, वे स्ट्रिंग सेटिंग्स के साथ आपके द्वारा की जाने वाली चीजों से बहुत अलग हैं, इसलिए क्या ऑपरेशन एक सामान्य इंटरफ़ेस में डालते हैं? जब तक आप कुछ के लिए जानते हैं, तब तक विवेकपूर्ण रूप से गतिशील टाइपिंग का उपयोग करना बेहतर है, और बाद में इसे ठोस बनाएं।
जॉन पूर्डी

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

@ जेटी: यह मूल रूप से एक ही समस्या है, हालांकि - एक सार्वभौमिक आधार वर्ग पहले स्थान पर मौजूद नहीं होना चाहिए क्योंकि, कोई फर्क नहीं पड़ता कि यह किस ऑपरेशन को परिभाषित करता है, एक प्रकार होगा जिसके लिए उन ऑपरेशनों का कोई मतलब नहीं है। लेकिन अगर C # के objectबजाय एक का उपयोग करना आसान बनाता है dynamic, तो सुनिश्चित करें, पूर्व का उपयोग करें।
जॉन प्यूरी

1
@ जेटी: यह बहुरूपता के बारे में है। सूची में "विषम" वस्तुओं की एक संख्या है, भले ही वे एक ही सुपरक्लास के उपवर्ग हो सकते हैं। जावा पॉइंट-ऑफ-व्यू से, आप कक्षा (या इंटरफ़ेस) की परिभाषाएँ सही पा सकते हैं। अन्य भाषाओं (LISP, Python, आदि) के लिए सभी घोषणाओं को सही होने का कोई लाभ नहीं है, क्योंकि व्यावहारिक कार्यान्वयन अंतर नहीं है।
S.Lott

2

कार्यात्मक भाषाओं (जैसे लिस्प) में, आप यह निर्धारित करने के लिए पैटर्न मिलान का उपयोग करते हैं कि किसी सूची में किसी विशेष तत्व का क्या होता है। C # में समतुल्य एक श्रृंखला होगी यदि ... अन्य कथन जो किसी तत्व के प्रकार की जांच करते हैं और उसी के आधार पर एक ऑपरेशन करते हैं। कहने की जरूरत नहीं है, कार्यात्मक पैटर्न मिलान रनटाइम प्रकार की जाँच से अधिक कुशल है।

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

public class ListVisitor
{
  public void DoSomething(IEnumerable<dynamic> list)
  {
    foreach(dynamic obj in list)
    {
       DoSomething(obj);
    }
  }

  public void DoSomething(SomeClass obj)
  {
    //do something with SomeClass
  }

  public void DoSomething(AnotherClass obj)
  {
    //do something with AnotherClass
  }

  public void DoSomething(Object obj)
  {
    //do something with everything els
  }
}

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

फ्लिप पक्ष उन सभी को सूचित कर रहा है जो एक संदेश के लिए रजिस्टर करते हैं (उदाहरण के लिए इवेंट एग्रीगेटर पैटर्न जो आमतौर पर MVVM पैटर्न में ViewModels के ढीले युग्मन के लिए उपयोग किया जाता है)। मैं निम्नलिखित निर्माण का उपयोग करता हूं

IDictionary<Type, List<Object>>

शब्दकोश में जोड़ने का एकमात्र तरीका एक फ़ंक्शन है

Register<T>(Action<T> handler)

(और वस्तु वास्तव में हैंडलर में पारित होने के लिए एक कमजोर संदर्भ है)। इसलिए यहाँ मुझे सूची <ऑब्जेक्ट> का उपयोग करना है क्योंकि संकलन के समय, मुझे नहीं पता कि बंद प्रकार क्या होगा। हालांकि रनटाइम पर मैं यह लागू कर सकता हूं कि यह उस प्रकार का होगा जो शब्दकोश की कुंजी है। जब मैं घटना को आग लगाना चाहता हूं

Send<T>(T message)

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


पैटर्न मिलान के साथ, डेटा प्रकार के मिलान की घोषणा के द्वारा मामले (आमतौर पर - कम से कम एमएल और हास्केल में) पत्थर में सेट होते हैं। ऐसे प्रकारों वाली सूचियाँ विषमलैंगिक नहीं होती हैं।

मुझे ML और हास्केल के बारे में निश्चित नहीं है, लेकिन एर्लैंग किसी भी माध्यम से मेल खा सकता है, यदि आप यहां तक ​​पहुंचे हैं क्योंकि कोई अन्य मैच संतुष्ट नहीं था, तो ऐसा करें।
माइकल ब्राउन

@ माइकबर्न - यह अच्छा है, लेकिन यह कवर क्यों नहीं करता है कि एक व्यक्ति विषम सूचियों का उपयोग करेगा और हमेशा सूची के साथ काम नहीं करेगा <गतिशील>
जेटी

4
C # में, अधिभार को संकलन समय पर हल किया जाता है । इस प्रकार, आपका उदाहरण कोड हमेशा कॉल करेगा DoSomething(Object)(कम से कम लूप objectमें उपयोग करते समय foreach; dynamicपूरी तरह से एक अलग चीज है)।
हेनजी

@ हेंज़ी, आप सही कह रहे हैं ... मुझे आज नींद आ रही है: पी फिक्स्ड
माइकल ब्राउन

0

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

मेरे अनुभव में, फ़ाइलों, नेटवर्क सॉकेट्स आदि के माध्यम से कच्चे बाइट्स से निपटना, आप अक्सर ऐसी समस्याओं में भाग लेते हैं।

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

ये रिकॉर्ड कहां रखे जा सकते हैं? सहज रूप से, आप जो चाहते हैं वह कुछ ऐसा है Dictionary<WorkId, Future<TValue>>, लेकिन यह आपको पूरे सिस्टम में केवल एक प्रकार के वायदा के प्रबंधन के लिए सीमित करता है। अधिक उपयुक्त प्रकार है Dictionary<WorkId, Future<dynamic>>, चूंकि कार्यकर्ता भविष्य के लिए मजबूर होने पर उपयुक्त प्रकार को डाल सकता है।

नोट : यह उदाहरण हास्केल की दुनिया से आता है जहाँ हमारे पास सबटाइपिंग नहीं है। मुझे आश्चर्य नहीं होगा यदि C # में इस विशेष उदाहरण के लिए एक और अधिक मुहावरेदार समाधान है, लेकिन यह अभी भी निराशाजनक है।


0

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

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