टैग यूनियन

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

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

टैग यूनियनों के साथ प्रायः एक प्रकार के निर्माता की अवधारणा जुड़ी होती है, जो क्लास के लिए निर्माता के समान है लेकिन समान नहीं होता है। प्रारंभिक टैग प्रकार और संबंधित प्रकार को ध्यान में रखते हुए, प्रकार निर्माता टैग यूनियन प्रकार का उत्पादन करते हैं।

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

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

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

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

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

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

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

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

कभी-कभी, अनटैग यूनियनों का उपयोग प्रकारों के बीच बिट-स्तरीय रूपांतरण करने के लिए किया जाता है, जिन्हें सी++ (C++) में पुनः व्याख्या विक्षेप कहा जाता है। टैग यूनियन इस उद्देश्य के लिए अभिप्रेत नहीं हैं प्रायः जब भी टैग बदला जाता है तो एक नया मान निर्दिष्ट किया जाता है।

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

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


 * $$\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}$$

जहां "मान" और "त्रुटि" यूनियन प्रकार के निर्माता हैं, A और B वैध परिणाम प्रकार हैं और E त्रुटि केसेस का प्रकार है। वैकल्पिक रूप से, उसी मोनाड को वापस और दो अतिरिक्त कार्यों, एफएमएपी (fmap) और संबद्ध द्वारा वर्णित किया जा सकता है-


 * $$\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}$$

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

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

जो इस ट्री के अनुरूप है-

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

1960s
एएलजीओएल (ALGOL) 68 में, टैग यूनियनों को संयुक्त मोड कहा जाता है, टैग अंतर्निहित है, और  निर्माण का उपयोग यह निर्धारित करने के लिए किया जाता है कि कौन सा क्षेत्र टैग किया गया है-

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

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

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

और यह एडा समकक्ष हैं- सी(C) और सी++ (C++) में, दृढ़ एक्सेस अनुशासन का उपयोग करके बिना टैग यूनियनों से टैग यूनियन बनाया जा सकता है, जहां टैग की सदैव जांच की जाती है-

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

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

2000s
C की एक उन्नत बोली जिसे साइक्लोन कहा जाता है, में टैग किए गए यूनियनों के लिए व्यापक अंतर्निहित सपोर्ट है।

रस्ट, हेक्स और स्विफ्ट भाषाओं में एनम प्रकार टैग यूनियनों के रूप में भी काम करते हैं।

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

F# ने यूनियनों के साथ विभेदीकृत किया है-

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

2010s
स्काला 3 में एनम्स जोड़े गए हैं, जिससे हमें पहले के स्काला उदाहरणों को अधिक संक्षेप में रीराइट की अनुमति मिलती है- रस्ट भाषा को टैग यूनियनों, जिन्हें एनम्स कहा जाता है, के लिए व्यापक सपोर्ट प्राप्त है। उदाहरण के लिए- यह यूनियनों पर मिलान की भी अनुमति देता है-

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

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

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

यह भी देखें

 * विविक्तकर, सीओआरबीए (CORBA) में विभेदित यूनियनों के लिए प्रकार टैग
 * वैरिएंट प्रकार (COM)

बाहरी संबंध

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