टैग की गई यूनियन

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

विवरण
एमएल [[प्रोग्रामिंग भाषा ]] और हास्केल (प्रोग्रामिंग भाषा)  जैसी कार्यात्मक भाषाओं में टैग किए गए संघ सबसे महत्वपूर्ण हैं, जहां उन्हें डेटाटाइप कहा जाता है (बीजगणितीय डेटा प्रकार देखें) और कंपाइलर यह सत्यापित करने में सक्षम है कि टैग किए गए यूनियन के सभी मामले हमेशा संभाले जाते हैं, परहेज करते हैं कई प्रकार की त्रुटियाँ। हालांकि, वे लगभग किसी भी प्रोग्रामिंग भाषा में बनाए जा सकते हैं, और अनटैग यूनियनों की तुलना में अधिक सुरक्षित हैं, जिन्हें अक्सर यूनियन कहा जाता है, जो समान हैं लेकिन स्पष्ट रूप से ट्रैक नहीं करते हैं कि यूनियन का कौन सा सदस्य वर्तमान में उपयोग में है।

टैग की गई यूनियनें अक्सर एक प्रकार के कंस्ट्रक्टर की अवधारणा के साथ होती हैं, जो एक क्लास के लिए एक कंस्ट्रक्टर (कंप्यूटर साइंस) के समान है लेकिन समान नहीं है। प्रारंभिक टैग प्रकार और संबंधित प्रकार दिए जाने पर कंस्ट्रक्टर टाइप करें एक टैग किए गए संघ प्रकार का उत्पादन करते हैं।

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

प्रकार सिद्धांत में, एक टैग किए गए संघ को योग प्रकार कहा जाता है। योग प्रकार उत्पाद प्रकार के दोहरे (गणित) हैं। नोटेशन भिन्न होते हैं, लेकिन आमतौर पर योग प्रकार $A + B$ दो परिचय रूपों (इंजेक्शन (गणित)) के साथ आता है $inj_{1}: A → A + B$ और $inj_{2}: B → A + B$. एलिमिनेशन फॉर्म केस एनालिसिस है, जिसे एमएल (प्रोग्रामिंग भाषा)  में  पैटर्न मिलान  के रूप में जाना जाता है | एमएल-स्टाइल प्रोग्रामिंग लैंग्वेज: अगर $e$ प्रकार है $A + B$ और $e_{1}$ और $e_{2}$ प्रकार है $$\tau$$ मान्यताओं के तहत $x: A$ और $y: B$ क्रमशः, फिर शब्द $$\mathsf{case}\ e\ \mathsf{of}\ x \Rightarrow e_1 \mid y \Rightarrow e_2$$ प्रकार है $$\tau$$. करी-हावर्ड पत्राचार के तहत योग प्रकार अंतर्ज्ञानवादी तर्क तार्किक संयोजन से मेल खाता है।

एक प्रगणित प्रकार को पतित मामले के रूप में देखा जा सकता है: इकाई प्रकारों का एक टैग किया गया संघ। यह अशक्त निर्माणकर्ताओं के एक सेट से मेल खाता है और इसे एक साधारण टैग चर के रूप में लागू किया जा सकता है, क्योंकि इसमें टैग के मूल्य के अलावा कोई अतिरिक्त डेटा नहीं है।

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

एक टैग किए गए संघ को डेटा क्रमांकन प्रारूपों की सबसे सरल प्रकार की आत्म-वर्णन तुलना के रूप में देखा जा सकता है। टैग किए गए संघ के टैग को सबसे सरल प्रकार के मेटा डेटा  के रूप में देखा जा सकता है।

फायदे और नुकसान
एक टैग नहीं किए गए संघ पर एक टैग किए गए संघ का प्राथमिक लाभ यह है कि सभी एक्सेस सुरक्षित हैं, और संकलक यह भी जांच सकता है कि सभी मामले संभाले गए हैं। अनटैग यूनियन वर्तमान में सक्रिय क्षेत्र की सही पहचान करने के लिए प्रोग्राम लॉजिक पर निर्भर करते हैं, जिसके परिणामस्वरूप अजीब व्यवहार हो सकता है और यदि तर्क विफल हो जाता है तो खोजने में कठिनाई होती है।

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

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

कभी-कभी, अनटैग यूनियनों का उपयोग प्रकारों के बीच बिट-स्तरीय रूपांतरण करने के लिए किया जाता है, जिसे सी ++ में रीइंटरप्रिट कास्ट कहा जाता है। टैग की गई यूनियनें इस उद्देश्य के लिए अभिप्रेत नहीं हैं; जब भी टैग बदला जाता है, आमतौर पर एक नया मान निर्दिष्ट किया जाता है।

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

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


 * $$\text{return}\colon A \to \left( A + E \right) = a \mapsto \text{value} \, a$$
 * $$\text{bind}\colon \left( A + E \right) \to \left(A \to \left(B + E \right) \right) \to \left( B + E \right) = a \mapsto f \mapsto \begin{cases} \text{err} \, e & \text{if} \ a = \text{err} \, e\\ f \, a' & \text{if} \ a = \text{value} \, a' \end{cases}$$

जहाँ value और err संघ प्रकार के निर्माता हैं, A और B मान्य परिणाम प्रकार हैं और E त्रुटि स्थितियों का प्रकार है। वैकल्पिक रूप से, एक ही सन्यासी को वापसी और दो अतिरिक्त कार्यों, fmap और join द्वारा वर्णित किया जा सकता है:


 * $$\text{fmap} \colon (A \to B) \to \left( \left( A + E \right) \to \left( B + E \right) \right) = f \mapsto a \mapsto \begin{cases} \text{err} \, e & \text{if} \ a = \text{err} \, e \\ \text{value} \, \text{(} \, f \, a' \, \text{)} & \text{if} \ a = \text{value} \, a' \end{cases}$$
 * $$\text{join} \colon ((A + E ) + E) \to (A + E) = a \mapsto \begin{cases} \text{err} \, e & \mbox{if} \ a = \text{err} \, e\\ \text{err} \, e & \text{if} \ a = \text{value} \, \text{(err} \, e \, \text{)} \\ \text{value} \, a' & \text{if} \ a = \text{value} \, \text{(value} \, a' \, \text{)} \end{cases}$$

उदाहरण
कहते हैं कि हम पूर्णांकों का एक बाइनरी ट्री बनाना चाहते हैं। एमएल में, हम इस तरह एक डेटाटाइप बनाकर ऐसा करेंगे:

यह दो मामलों के साथ एक टैग किया गया संघ है: एक, पत्ता, पेड़ के पथ को समाप्त करने के लिए प्रयोग किया जाता है, और अनिवार्य भाषाओं में शून्य मान की तरह कार्य करता है। दूसरी शाखा में एक नोड होता है, जिसमें एक पूर्णांक और एक बाएँ और दाएँ सबट्री होता है। लीफ और नोड कंस्ट्रक्टर हैं, जो हमें वास्तव में एक विशेष पेड़ बनाने में सक्षम बनाते हैं, जैसे:

जो इस पेड़ से मेल खाता है:

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

1960 के दशक
ALGOL 68 में, टैग की गई यूनियनों को संयुक्त मोड कहा जाता है, टैग निहित है, और  निर्माण का उपयोग यह निर्धारित करने के लिए किया जाता है कि किस क्षेत्र को टैग किया गया है:

उपयोग उदाहरण के लिए    का  :

नोड n := 1234 ; मामला एन में (वास्तविक आर): प्रिंट (( वास्तविक:, आर)), (इंट आई): प्रिंट ((इंट:, आई)), (शिकायत c): प्रिंट (( शिकायत:, c)), (स्ट्रिंग एस): प्रिंट (( स्ट्रिंग: एस)) आउट प्रिंट (( ?:, एन)) esac

1970 और 1980 के दशक
हालांकि मुख्य रूप से केवल कार्यात्मक प्रोग्रामिंग भाषा जैसे एमएल प्रोग्रामिंग भाषा (1970 के दशक से) और हास्केल (प्रोग्रामिंग भाषा) (1990 के दशक से) टैग की गई यूनियनों को एक केंद्रीय भूमिका देती हैं और यह जांचने की शक्ति रखती हैं कि सभी मामलों को संभाला जाता है, अन्य भाषाओं में समर्थन है टैग किए गए यूनियनों के लिए भी। हालांकि, व्यवहार में वे गैर-कार्यात्मक भाषाओं में कार्यात्मक भाषा संकलक द्वारा सक्षम अनुकूलन के कारण कम कुशल हो सकते हैं जो स्पष्ट टैग चेक और विलोपन टाइप करें को समाप्त कर सकते हैं।

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

और यह ऐडा समकक्ष: सी (प्रोग्रामिंग भाषा) और सी ++ में, टैग किए गए यूनियनों को सख्त पहुंच अनुशासन का उपयोग करके टैग किए गए यूनियनों से बनाया जा सकता है जहां टैग हमेशा चेक किया जाता है:

जब तक संघ क्षेत्रों को केवल कार्यों के माध्यम से एक्सेस किया जाता है, तब तक पहुंच सुरक्षित और सही होगी। एन्कोडेड टैग के लिए समान दृष्टिकोण का उपयोग किया जा सकता है; हम केवल टैग को डिकोड करते हैं और फिर प्रत्येक एक्सेस पर इसकी जांच करते हैं। यदि इन टैग जांचों की अक्षमता चिंता का विषय है, तो वे अंतिम संस्करण में स्वचालित रूप से हटा दिए जा सकते हैं।

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

2000s
C की एक उन्नत बोली जिसे चक्रवात प्रोग्रामिंग भाषा  कहा जाता है, में टैग किए गए यूनियनों के लिए व्यापक अंतर्निहित समर्थन है। जंग (प्रोग्रामिंग भाषा), हैक्स (प्रोग्रामिंग भाषा)  और  स्विफ्ट (प्रोग्रामिंग भाषा)  लैंग्वेज में एनम प्रकार भी टैग किए गए यूनियनों के रूप में काम करते हैं।

सी ++ पुस्तकालयों को बढ़ावा दें के वैरिएंट लाइब्रेरी ने प्रदर्शित किया है कि सी++ में एक लाइब्रेरी के रूप में एक सुरक्षित टैग किए गए संघ को लागू करना संभव था, जिसे फंक्शन ऑब्जेक्ट्स का उपयोग करके देखा जा सकता है। स्काला (प्रोग्रामिंग भाषा) में केस क्लासेस हैं: क्योंकि वर्ग पदानुक्रम को सील कर दिया गया है, संकलक यह जांच सकता है कि सभी मामले एक पैटर्न मैच में संभाले गए हैं: स्काला मामला वर्ग भी उपप्रकार के माध्यम से पुन: उपयोग की अनुमति देता है:

एफ शार्प (प्रोग्रामिंग लैंग्वेज) | एफ # ने यूनियनों में भेदभाव किया है:

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

2010
स्कैला 3 में Enums जोड़े गए हैं, हमें पहले के स्काला उदाहरणों को और अधिक संक्षेप में फिर से लिखने की अनुमति देता है: रस्ट (प्रोग्रामिंग लैंग्वेज) को टैग किए गए संघों के लिए व्यापक समर्थन प्राप्त है, जिन्हें एनम कहा जाता है। उदाहरण के लिए: यह यूनियनों पर मिलान की भी अनुमति देता है:

रस्ट का एरर हैंडलिंग मॉडल इन टैग किए गए यूनियनों पर बड़े पैमाने पर निर्भर करता है, विशेष रूप से  प्रकार, जो या तो है   या , और यह   प्रकार, जो या तो है   या. स्विफ्ट (प्रोग्रामिंग लैंग्वेज) को भी गणनाओं के माध्यम से टैग किए गए संघों के लिए पर्याप्त समर्थन प्राप्त है। उदाहरण के लिए: टाइपप्रति  के साथ टैग किए गए यूनियनों को भी बनाना संभव है। उदाहरण के लिए: Python 3.9 टाइपिंग एनोटेशन के लिए समर्थन पेश करता है जिसका उपयोग टैग किए गए संघ प्रकार (PEP-593) को परिभाषित करने के लिए किया जा सकता है ): C++17 पेश करता है std::variant और constexpr if

वृक्ष = एसटीडी का उपयोग :: संस्करण <संरचना पत्ता, संरचना नोड>;

संरचना पत्ता { एसटीडी :: स्ट्रिंग मान; }; संरचना नोड { ट्री* लेफ्ट = नलप्टर; ट्री* राइट = नलप्टर; };

संरचना ट्रांसवर्सर { टेम्पलेट <टाइपनेम टी> शून्य ऑपरेटर (टी एंड& वी) {   if constexpr (std::is_same_v) {     एसटीडी :: अदालत << v.value << \n; }   और अगर constexpr (std::is_same_v) {     अगर (v.बाएँ! = अशक्त) एसटीडी :: यात्रा (ट्रांसवर्सर {}, * v.बाएं);

अगर (v.right!= nullptr) एसटीडी :: यात्रा (ट्रांसवर्सर {}, * v.right); }   अन्य {     // !sizeof(T) व्यंजक हमेशा गलत होता है static_assert(!sizeof(T), गैर-संपूर्ण आगंतुक! ); }; } }; /*वृक्ष वन = ...; एसटीडी :: यात्रा (ट्रांसवर्सर {}, वन); * /



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

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

यह भी देखें

 * discriminator, CORBA में भेदभावपूर्ण यूनियनों के लिए टाइप टैग
 * भिन्न प्रकार (COM)

बाहरी संबंध

 * boost::variant is a C++ typesafe discriminated union
 * std.variant is an implementation of variant type in D 2.0