टैग यूनियन

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

विवरण
एमएल (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}$$

जहां मान और त्रुटि यूनियन प्रकार के निर्माता हैं, ए और बी वैध परिणाम प्रकार हैं और ई त्रुटि स्थितियों का प्रकार है। वैकल्पिक रूप से, उसी मोनड को रिटर्न और दो अतिरिक्त कार्यों, एफएमएपी और जॉइन द्वारा वर्णित किया जा सकता है:


 * $$\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 ; केस एन इन (असली आर): प्रिंट(( असली:, आर)), (int i): प्रिंट(( int:, i)), (compl c): प्रिंट((compli:, c)), (स्ट्रिंग एस): प्रिंट(( स्ट्रिंग:, एस)) प्रिंट आउट(( ?:, n)) esac

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

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

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

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

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

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

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

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

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

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

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

ट्री = std::variant का उपयोग करना;

संरचना पत्ता { std::स्ट्रिंग मान; }; संरचना नोड { पेड़* बाएँ = nullptr; वृक्ष* दाएँ = nullptr; };

संरचना ट्रांसवर्सर { टेम्प्लेट<नाम टाइप करें टी> शून्य ऑपरेटर(टी&& वी) {   यदि constexpr (std::is_same_v) {     std::cout << v.value << \n ; }   अन्यथा यदि constexpr (std::is_same_v) {     यदि (v.बाएँ !=nullptr) std::visit(Transverser{}, *v.left);

यदि (v.right !=nullptr) std::visit(Transverser{}, *v.right); }   अन्य {     // !sizeof(T) अभिव्यक्ति हमेशा झूठी होती है static_assert(!sizeof(T), गैर-संपूर्ण विज़िटर! ); }; } }; /*पेड़ जंगल =...; std::विज़िट(ट्रांसवर्सर{}, वन);*/



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

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

यह भी देखें

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

बाहरी संबंध

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