टैग यूनियन: Difference between revisions
No edit summary |
|||
| Line 17: | Line 17: | ||
==लाभ और हानि== | ==लाभ और हानि== | ||
अलग्न संघ की तुलना में संलग्न संघ का प्राथमिक लाभ यह है कि सभी एक्सेस सुरक्षित हैं, और संकलक यह भी जांच सकता है कि सभी स्थितियों को संभाला गया है। अलग्न संघ वर्तमान में सक्रिय क्षेत्र की सही पहचान करने के लिए प्रोग्राम तर्क पर निर्भर करता हैं, जिसके परिणामस्वरूप अजीब व्यवहार हो सकता है और यदि वह तर्क विफल हो जाता है तो बग ढूंढना मुश्किल हो सकता है। | |||
प्रत्येक प्रकार के लिए | प्रत्येक प्रकार के लिए क्षेत्र वाले साधारण [[रिकॉर्ड (कंप्यूटर विज्ञान)|रिकॉर्ड]] की तुलना में संलग्न संघ का प्राथमिक लाभ यह है कि यह सभी प्रकार के लिए स्टोरेज को ओवरलैप करके स्टोरेज बचाता है। कुछ कार्यान्वयन सबसे बड़े प्रकार के लिए पर्याप्त स्टोरेज आरक्षित रखते हैं, जबकि अन्य आवश्यकतानुसार संलग्न संघ मान के आकार को गतिशील रूप से समायोजित करते हैं। जब मान [[अपरिवर्तनीय वस्तु|अपरिवर्तनीय]] होता है, तो उतनी ही स्टोरेज आवंटित करना आसान होता है जितनी आवश्यकता होती है। | ||
संलग्न संघों का मुख्य हानि यह है कि टैग स्थान घेरता है। चूँकि प्रायः बहुत कम संख्या में विकल्प होते हैं, संलग्न को प्रायः जहां भी स्थान मिलता है, 2 या 3 बिट्स में निष्पीडित किया जा सकता है, लेकिन कभी-कभी ये बिट्स भी उपलब्ध नहीं होते हैं। इस स्थिति में, सहायक विकल्प संलग्न को '''मोड़ना''', '''गणना करना''' या '''एन्कोड करना''' हो सकता है, जहां संलग्न मान की गणना संंघ क्षेत्र की सामग्री से गतिशील रूप से की जाती है। इसके सामान्य उदाहरण आरक्षित मानों का उपयोग हैं, उदाहरण के लिए, सकारात्मक संख्या वापस लाने वाला फ़ंक्शन विफलता को इंगित करने के लिए -1 वापस कर सकता है, और प्रहरी मान, जो प्रायः संलग्न संकेतों में उपयोग किए जाते हैं। | |||
कभी-कभी, | कभी-कभी, अलग्न संघों का उपयोग प्रकारों के बीच बिट-स्तरीय रूपांतरण करने के लिए किया जाता है, जिन्हें सी++ (C++) में पुनः व्याख्या विक्षेप कहा जाता है। संलग्न संघ इस उद्देश्य के लिए अभिप्रेत नहीं हैं प्रायः जब भी संलग्न बदला जाता है तो एक नया मान निर्दिष्ट किया जाता है। | ||
कई भाषाएँ, कुछ हद तक, | कई भाषाएँ, कुछ हद तक, सार्वभौमिक डेटा [[शीर्ष प्रकार|प्रकार]] का समर्थन करती हैं, जो एक ऐसा प्रकार है जिसमें प्रत्येक दूसरे प्रकार का प्रत्येक मान सम्मिलित होता है, और प्रायः सार्वभौमिक प्रकार के मान के वास्तविक प्रकार का परीक्षण करने का तरीका प्रदान किया जाता है। इन्हें कभी-कभी ''परिवर्ती'' के रूप में भी जाना जाता है। जबकि सार्वभौमिक डेटा प्रकार उनकी औपचारिक परिभाषा में संलग्न संघों के साथ तुलनीय हैं, विशिष्ट संलग्न संघों में अपेक्षाकृत कम संख्या में स्थितियां सम्मिलित होती हैं, और ये स्थितियां एकल सुसंगत अवधारणा को व्यक्त करने के विभिन्न तरीके बनाते हैं, जैसे डेटा संरचना नोड या निर्देश। साथ ही, यह भी अपेक्षा है कि संलग्न संघ का उपयोग किए जाने पर उसके प्रत्येक संभावित स्थिति से निपटा जाएगा। सार्वभौमिक डेटा प्रकार के मान संबंधित नहीं हैं और उन सभी से निपटने का कोई व्यवहार्य तरीका नहीं है। | ||
[[विकल्प प्रकार]] और अपवाद प्रबंधन की तरह, | [[विकल्प प्रकार]] और अपवाद प्रबंधन की तरह, संलग्न संघों का उपयोग कभी-कभी असाधारण परिणामों की घटना को संभालने के लिए किया जाता है। प्रायः इन संलग्नों को आरक्षित मानों के रूप में मोड़ दिया जाता है, और उनकी घटना की लगातार जांच नहीं की जाती है: यह प्रोग्रामिंग त्रुटियों का काफी सामान्य स्रोत है। संलग्न संघों के इस उपयोग को निम्नलिखित कार्यों के साथ [[मोनाड (कार्यात्मक प्रोग्रामिंग)|मोनाड]] के रूप में औपचारिक रूप दिया जा सकता है- | ||
:<math>\text{return}\colon A \to \left( A + E \right) = a \mapsto \text{value} \, a</math> | :<math>\text{return}\colon A \to \left( A + E \right) = a \mapsto \text{value} \, a</math> | ||
:<math>\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}</math> | :<math>\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}</math> | ||
जहां मान और त्रुटि | जहां "मान" और "त्रुटि" संघ प्रकार के निर्माता हैं, ''A'' और ''B'' वैध परिणाम प्रकार हैं और ''E'' त्रुटि स्थितियों का प्रकार है। वैकल्पिक रूप से, उसी मोनाड को वापस और दो अतिरिक्त कार्यों, एफएमएपी (''fmap'') और ''संबद्ध'' द्वारा वर्णित किया जा सकता है- | ||
:<math>\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}</math> | :<math>\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}</math> | ||
:<math>\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}</math> | :<math>\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}</math> | ||
==उदाहरण== | ==उदाहरण== | ||
मान लें कि हम पूर्णांकों का | मान लें कि हम पूर्णांकों का [[द्विआधारी वृक्ष|बाइनरी ट्री]] बनाना चाहते थे। एमएल में, हम इस तरह डेटाप्रकार बनाकर ऐसा करेंगे- | ||
<syntaxhighlight lang="sml"> | <syntaxhighlight lang="sml"> | ||
| Line 42: | Line 42: | ||
| Node of (int * tree * tree) | | Node of (int * tree * tree) | ||
</syntaxhighlight> | </syntaxhighlight> | ||
यह दो | यह दो स्थितियों के साथ संलग्न संघ है- एक, लीफ, का उपयोग ट्री के पथ को समाप्त करने के लिए किया जाता है, और अनिवार्य भाषाओं में शून्य मान की तरह कार्य करता है। दूसरी शाखा में नोड होता है, जिसमें एक पूर्णांक और बाएं और दाएं सबट्री होता है। लीफ और नोड निर्माता हैं, जो हमें वास्तव में विशेष ट्री बनाने में सक्षम बनाते हैं, जैसे- | ||
<syntaxhighlight lang="sml"> | <syntaxhighlight lang="sml"> | ||
Node(5, Node(1, Leaf, Leaf), Node(3, Leaf, Node(4, Leaf, Leaf))) | Node(5, Node(1, Leaf, Leaf), Node(3, Leaf, Node(4, Leaf, Leaf))) | ||
</syntaxhighlight> | </syntaxhighlight> | ||
जो इस | जो इस ट्री के अनुरूप है- | ||
[[File:tagged union tree.svg|उपरोक्त कंस्ट्रक्टर्स|सेंटर द्वारा निर्मित पेड़]]अब हम आसानी से | [[File:tagged union tree.svg|उपरोक्त कंस्ट्रक्टर्स|सेंटर द्वारा निर्मित पेड़]]अब हम आसानी से टाइपसेफ़ फ़ंक्शन लिख सकते हैं जो, मान लीजिए, ट्री में नोड्स की संख्या की गणना करता है- | ||
<syntaxhighlight lang="sml"> | <syntaxhighlight lang="sml"> | ||
| Line 56: | Line 56: | ||
1 + countNodes(left) + countNodes(right) | 1 + countNodes(left) + countNodes(right) | ||
</syntaxhighlight> | </syntaxhighlight> | ||
==भाषा समर्थन की समयरेखा== | ==भाषा समर्थन की समयरेखा== | ||
=== | ===1960s=== | ||
[[ALGOL 68]] में, | [[ALGOL 68|एएलजीओएल (ALGOL) 68]] में, संलग्न संघों को ''संयुक्त मोड'' कहा जाता है, संलग्न अंतर्निहित है, और <code>'''case'''</code> निर्माण का उपयोग यह निर्धारित करने के लिए किया जाता है कि कौन सा क्षेत्र संलग्न किया गया है- | ||
<code>'''mode''' '''node''' = '''union''' ('''real''', '''int''', '''compl''', '''string''');</code> | <code>'''mode''' '''node''' = '''union''' ('''real''', '''int''', '''compl''', '''string''');</code> | ||
<code>'''node'''</code> के <code>'''union'''</code> <code>'''case'''</code> के लिए उपयोग उदाहरण-<syntaxhighlight lang="html"> | |||
node n := "1234"; | |||
case n in | |||
(real r): print(("real:", r)), | |||
(int i): print(("int:", i)), | |||
(compl c): print(("compl:", c)), | |||
(string s): print(("string:", s)) | |||
out print(("?:", n)) | |||
esac | |||
</syntaxhighlight> | |||
=== | ===1970s और 1980s=== | ||
हालाँकि मुख्य रूप से केवल कार्यात्मक प्रोग्रामिंग भाषाएँ जैसे एमएल | हालाँकि मुख्य रूप से केवल कार्यात्मक प्रोग्रामिंग भाषाएँ जैसे एमएल (1970 के दशक से) और हास्केल (1990 के दशक से) संलग्न संघों को केंद्रीय भूमिका देती हैं और यह जाँचने की शक्ति रखती हैं कि सभी स्थितियों को संभाला जाता है, अन्य भाषाएँ भी संलग्न संघों का समर्थन करती हैं। हालाँकि, व्यवहार में वे कार्यात्मक भाषा संकलकों द्वारा सक्षम किए गए अनुकूलन के कारण गैर-कार्यात्मक भाषाओं में कम कुशल हो सकते हैं जो स्पष्ट संलग्न जांच को समाप्त कर सकते हैं और संलग्न के स्पष्ट स्टोरेज से बच सकते हैं।{{Citation needed|date=January 2017}} | ||
[[पास्कल (प्रोग्रामिंग भाषा)]], [[एडा (प्रोग्रामिंग भाषा)]] | [[पास्कल (प्रोग्रामिंग भाषा)|पास्कल]], [[एडा (प्रोग्रामिंग भाषा)|एडा]] और [[मॉड्यूल-2|मोडुला-2]] उन्हें ''परिवर्ती रिकॉर्ड'' (एडा में औपचारिक रूप से विभेदित प्रकार) कहते हैं, और संलग्न क्षेत्र को मैन्युअल रूप से बनाने और संलग्न मान निर्दिष्ट करने की आवश्यकता होती है, जैसा कि इस पास्कल उदाहरण में है- | ||
<syntaxhighlight lang="pascal"> | <syntaxhighlight lang="pascal"> | ||
| Line 92: | Line 91: | ||
end; | end; | ||
</syntaxhighlight> | </syntaxhighlight> | ||
और यह | और यह एडा समकक्ष हैं- | ||
<syntaxhighlight lang="ada"> | <syntaxhighlight lang="ada"> | ||
type Shape_Kind is (Square, Rectangle, Circle); | type Shape_Kind is (Square, Rectangle, Circle); | ||
| Line 112: | Line 111: | ||
-- discriminant is not the expected one, raises an error. | -- discriminant is not the expected one, raises an error. | ||
</syntaxhighlight> | </syntaxhighlight> | ||
[[सी (प्रोग्रामिंग भाषा)]] और सी ++ में, | [[सी (प्रोग्रामिंग भाषा)|सी(C)]] और सी++ (C++) में, दृढ़ एक्सेस अनुशासन का उपयोग करके बिना संलग्न संघों से संलग्न संघ बनाया जा सकता है, जहां संलग्न की सदैव जांच की जाती है- | ||
<syntaxhighlight lang="c"> | <syntaxhighlight lang="c"> | ||
| Line 140: | Line 139: | ||
/* and so on */ | /* and so on */ | ||
</syntaxhighlight> | </syntaxhighlight> | ||
जब तक | जब तक संघ क्षेत्र को केवल फ़ंक्शंस के माध्यम से एक्सेस किया जाता है, तब तक एक्सेस सुरक्षित और सही रहेगा। एन्कोडेड संलग्न के लिए उसी दृष्टिकोण का उपयोग किया जा सकता है हम केवल संलग्न को डिकोड करते हैं और फिर प्रत्येक एक्सेस पर इसकी जांच करते हैं। यदि इन संलग्न जांचों की अक्षमता चिंता का विषय है, तो अंतिम संस्करण में उन्हें स्वचालित रूप से हटाया जा सकता है। | ||
सी और सी++ में विशेष संलग्न संघ के लिए भाषा समर्थन भी है- संभवतः-शून्य [[पॉइंटर (कंप्यूटर प्रोग्रामिंग)|सूचक]]। इसकी तुलना एमएल में <code>option</code> प्रकार या हास्केल में <code>Maybe</code> प्रकार से की जा सकती है, और इसे [[नल पॉइंटर|संलग्न सूचक]] के रूप में देखा जा सकता है- दो प्रकार का संलग्न संघ (एन्कोडेड संलग्न के साथ)- | |||
* मान्य सूचक, | |||
* केवल एक मान वाला शून्य सूचक प्रकार, <code>null</code>, असाधारण स्थिति का संकेत देता है। | |||
दुर्भाग्य से, सी संकलक यह सत्यापित नहीं करते हैं कि अशक्त स्थिति को सदैव संभाला जाता है, और यह सी कोड में त्रुटियों का विशेष रूप से प्रचलित स्रोत है, क्योंकि असाधारण स्थितियों को अनदेखा करने की प्रवृत्ति होती है। | |||
===2000s=== | |||
सी की एक उन्नत बोली जिसे साइक्लोन कहा जाता है, में टैग किए गए संघों के लिए व्यापक अंतर्निहित समर्थन है।<ref>{{Cite web|url=http://cyclone.thelanguage.org/wiki/Tagged%20Unions|title=Cyclone: Tagged Unions}}</ref> | |||
रस्ट, [[ मिला हुआ |हेक्स]] और [[स्विफ्ट (प्रोग्रामिंग भाषा)|स्विफ्ट भाषाओं]] में एनम प्रकार संलग्न संघों के रूप में भी काम करते हैं। | |||
रस्ट | |||
[[ C++ लाइब्रेरीज़ को बूस्ट करें ]] | [[ C++ लाइब्रेरीज़ को बूस्ट करें |बूस्ट सी++ लाइब्रेरीज़]] की परिवर्ती लाइब्रेरी ने प्रदर्शित किया कि सी++ में लाइब्रेरी के रूप में सुरक्षित संलग्न संघ को कार्यान्वित करना संभव है, जिसे फ़ंक्शन ऑब्जेक्ट का उपयोग करके देखा जा सकता है।<syntaxhighlight lang="cpp"> | ||
<syntaxhighlight lang="cpp"> | |||
struct display : boost::static_visitor<void> | struct display : boost::static_visitor<void> | ||
{ | { | ||
| Line 172: | Line 171: | ||
boost::apply_visitor(display(), v); | boost::apply_visitor(display(), v); | ||
</syntaxhighlight> | </syntaxhighlight> | ||
[[स्काला (प्रोग्रामिंग भाषा)]] में | [[स्काला (प्रोग्रामिंग भाषा)|स्काला]] में स्थिति वर्ग हैं- | ||
<syntaxhighlight lang="scala"> | <syntaxhighlight lang="scala"> | ||
sealed abstract class Tree | sealed abstract class Tree | ||
| Line 180: | Line 179: | ||
val tree = Node(5, Node(1, Leaf, Leaf), Node(3, Leaf, Node(4, Leaf, Leaf))) | val tree = Node(5, Node(1, Leaf, Leaf), Node(3, Leaf, Node(4, Leaf, Leaf))) | ||
</syntaxhighlight> | </syntaxhighlight> | ||
क्योंकि वर्ग पदानुक्रम | क्योंकि वर्ग पदानुक्रम बंद कर दिया गया है, संकलक यह जांच सकता है कि सभी स्थितियों को पैटर्न मिलान में संभाला गया है- | ||
<syntaxhighlight lang="scala"> | <syntaxhighlight lang="scala"> | ||
tree match { | tree match { | ||
| Line 187: | Line 186: | ||
} | } | ||
</syntaxhighlight> | </syntaxhighlight> | ||
स्काला | स्काला स्थिति वर्ग उपप्रकार के माध्यम से पुन: उपयोग की अनुमति भी देते हैं- | ||
<syntaxhighlight lang="scala"> | <syntaxhighlight lang="scala"> | ||
| Line 195: | Line 194: | ||
case class Circle(radius: Int, centerX: Int, centerY: Int) extends Shape(centerX, centerY) | case class Circle(radius: Int, centerX: Int, centerY: Int) extends Shape(centerX, centerY) | ||
</syntaxhighlight> | </syntaxhighlight> | ||
F# ने संघों के साथ विभेदीकृत किया है- | |||
<syntaxhighlight lang="fsharp"> | <syntaxhighlight lang="fsharp"> | ||
| Line 204: | Line 203: | ||
let tree = Node(5, Node(1, Leaf, Leaf), Node(3, Leaf, Node(4, Leaf, Leaf))) | let tree = Node(5, Node(1, Leaf, Leaf), Node(3, Leaf, Node(4, Leaf, Leaf))) | ||
</syntaxhighlight> | </syntaxhighlight> | ||
क्योंकि परिभाषित | क्योंकि परिभाषित स्थिति संपूर्ण हैं, संकलक यह जांच सकता है कि सभी स्थितियों को पैटर्न मिलान में नियंत्रित किया गया है- | ||
<syntaxhighlight lang="fsharp"> | <syntaxhighlight lang="fsharp"> | ||
match tree with | match tree with | ||
| Line 210: | Line 209: | ||
| Leaf -> printfn "top level node is a leaf" | | Leaf -> printfn "top level node is a leaf" | ||
</syntaxhighlight> | </syntaxhighlight> | ||
हेक्स | हेक्स का एनम संलग्न संघों के रूप में भी काम करता हैं-<ref>{{cite web|title=एनम्स का उपयोग करना - हेक्स - क्रॉस-प्लेटफ़ॉर्म टूलकिट|url=https://haxe.org/manual/types-enum-using.html|publisher=Haxe Foundation}}</ref> | ||
<syntaxhighlight lang="haxe"> | <syntaxhighlight lang="haxe"> | ||
enum Color { | enum Color { | ||
| Line 219: | Line 218: | ||
} | } | ||
</syntaxhighlight> | </syntaxhighlight> | ||
इनका मिलान स्विच अभिव्यक्ति का उपयोग करके किया जा सकता है- | |||
<syntaxhighlight lang="haxe"> | <syntaxhighlight lang="haxe"> | ||
switch (color) { | switch (color) { | ||
| Line 227: | Line 226: | ||
case Rgb(r, g, b): trace("Color had a red value of " +r); | case Rgb(r, g, b): trace("Color had a red value of " +r); | ||
} | } | ||
</syntaxhighlight>[[निम (प्रोग्रामिंग भाषा)]] | </syntaxhighlight>[[निम (प्रोग्रामिंग भाषा)|निम]] के पास पास्कल और एडा की घोषणा के समान ऑब्जेक्ट परिवर्ती<ref>{{Cite web|url=https://nim-lang.org/docs/manual.html#types-object-variants|title=निम मैनुअल|website=nim-lang.org|access-date=2020-01-23}}</ref> हैं-<syntaxhighlight lang="nim"> | ||
type | type | ||
ShapeKind = enum | ShapeKind = enum | ||
| Line 240: | Line 239: | ||
of skCircle: | of skCircle: | ||
radius: int | radius: int | ||
</syntaxhighlight>[[मैक्रो (कंप्यूटर विज्ञान)]] का उपयोग पैटर्न मिलान का अनुकरण करने या ऑब्जेक्ट | </syntaxhighlight>[[मैक्रो (कंप्यूटर विज्ञान)|मैक्रोज़]] का उपयोग पैटर्न मिलान का अनुकरण करने या ऑब्जेक्ट परिवर्ती घोषित करने के लिए सिंटैक्टिक शुगर बनाने के लिए किया जा सकता है, जिसे यहां पैकेज [https://github.com/andreaferretti/patty पैटी] द्वारा कार्यान्वित किया गया है-<syntaxhighlight lang="nim"> | ||
import patty | import patty | ||
| Line 265: | Line 264: | ||
echo sum(list(1, 2, 3, 4, 5)) | echo sum(list(1, 2, 3, 4, 5)) | ||
</syntaxhighlight> | </syntaxhighlight> | ||
=== 2010s === | |||
स्काला 3 में एनम्स जोड़े गए हैं,<ref>{{cite web|title=Scala 3 Language Reference: Enumerations|url=https://docs.scala-lang.org/scala3/reference/enums/enums.html|publisher=The Scala Team}}</ref> जिससे हमें पहले के स्काला उदाहरणों को अधिक संक्षेप में फिर से लिखने की अनुमति मिलती है- | |||
स्काला 3 में | |||
<syntaxhighlight lang="scala"> | <syntaxhighlight lang="scala"> | ||
enum Tree[+T]: | enum Tree[+T]: | ||
| Line 280: | Line 277: | ||
case Circle(radius: Int, centerX: Int, centerY: Int) extends Shape(centerX, centerY) | case Circle(radius: Int, centerX: Int, centerY: Int) extends Shape(centerX, centerY) | ||
</syntaxhighlight> | </syntaxhighlight> | ||
रस्ट | रस्ट भाषा को संलग्न संघों, जिन्हें एनम्स कहा जाता है, के लिए व्यापक समर्थन प्राप्त है।<ref>{{cite web|title=जंग प्रोग्रामिंग भाषा|url=http://rustbyexample.com/custom_types/structs.html|publisher=Mozilla}}</ref> उदाहरण के लिए- | ||
<syntaxhighlight lang="rust"> | <syntaxhighlight lang="rust"> | ||
enum Tree { | enum Tree { | ||
| Line 287: | Line 284: | ||
} | } | ||
</syntaxhighlight> | </syntaxhighlight> | ||
यह | यह संघों पर मिलान की भी अनुमति देता है- | ||
<syntaxhighlight lang="rust"> | <syntaxhighlight lang="rust"> | ||
| Line 306: | Line 303: | ||
assert_eq!(add_values(tree), 9); | assert_eq!(add_values(tree), 9); | ||
</syntaxhighlight> | </syntaxhighlight> | ||
रस्ट का त्रुटि प्रबंधन मॉडल बड़े पैमाने पर इन | रस्ट का त्रुटि प्रबंधन मॉडल बड़े पैमाने पर इन संंलग्न संघों पर निर्भर करता है, विशेष रूप से <code>Option<T></code> प्रकार, जो या तो <code>None</code> या <code>Some(T)</code> है, और <code>Result<T, E></code> प्रकार, जो या तो <code>Ok(T)</code> या <code>Err(E)</code> है।<ref>{{cite web|title=उदाहरण के द्वारा जंग|url=https://doc.rust-lang.org/stable/book/error-handling.html#the-option-type|publisher=Mozilla}}</ref> | ||
गणनाओं के माध्यम से संलग्न संघों के लिए स्विफ्ट को भी पर्याप्त समर्थन प्राप्त है।<ref>{{Cite web|title=Enumerations — The Swift Programming Language (Swift 5.4)|url=https://docs.swift.org/swift-book/LanguageGuide/Enumerations.html|access-date=2021-04-28|website=docs.swift.org}}</ref> उदाहरण के लिए-<syntaxhighlight lang="swift"> | |||
enum Tree { | enum Tree { | ||
case leaf | case leaf | ||
| Line 331: | Line 328: | ||
assert(add_values(tree) == 9) | assert(add_values(tree) == 9) | ||
</syntaxhighlight>[[ टाइपप्रति ]] | </syntaxhighlight>[[ टाइपप्रति |टाइपस्क्रिप्ट]] के साथ संलग्न संघ बनाना भी संभव है। उदाहरण के लिए- | ||
<syntaxhighlight lang="typescript"> | <syntaxhighlight lang="typescript"> | ||
| Line 373: | Line 370: | ||
} | } | ||
} | } | ||
</syntaxhighlight>[https://www.python.org/dev/peps/pep-0596/ | </syntaxhighlight>[https://www.python.org/dev/peps/pep-0596/ पायथन 3.9] एनोटेशन टाइपिंग के लिए समर्थन प्रस्तुत करता है जिसका उपयोग संलग्न संघ प्रकार (पीईपी-593<ref>{{Cite web|title=PEP 593 -- Flexible function and variable annotations|url=https://www.python.org/dev/peps/pep-0593/|access-date=2021-06-20|website=Python.org|language=en}}</ref>) को परिभाषित करने के लिए किया जा सकता है- <syntaxhighlight lang="python"> | ||
Currency = Annotated[ | Currency = Annotated[ | ||
TypedDict('Currency', {'dollars': float, 'pounds': float}, total=False), | TypedDict('Currency', {'dollars': float, 'pounds': float}, total=False), | ||
TaggedUnion, | TaggedUnion, | ||
] | ] | ||
</syntaxhighlight>[[C++17]] | </syntaxhighlight>[[C++17]] std::variant और [https://en.cppreference.com/w/cpp/भाषा/if constexpr if] का परिचय देता है<syntaxhighlight lang="swift"> | ||
using Tree = std::variant<struct Leaf, struct Node>; | |||
struct Leaf | |||
{ | { | ||
std:: | std::string value; | ||
}; | }; | ||
struct Node | |||
{ | { | ||
Tree* left = nullptr; | |||
Tree* right = nullptr; | |||
}; | }; | ||
struct Transverser | |||
{ | { | ||
template<typename T> | |||
void operator()(T&& v) | |||
{ | { | ||
if constexpr (std::is_same_v<T, Leaf&>) | |||
{ | { | ||
std::cout << v.value << \n ; | std::cout << v.value << "\n"; | ||
} | } | ||
else if constexpr (std::is_same_v<T, Node&>) | |||
{ | { | ||
if (v.left != nullptr) | |||
std::visit(Transverser{}, *v.left); | std::visit(Transverser{}, *v.left); | ||
if (v.right != nullptr) | |||
std::visit(Transverser{}, *v.right); | std::visit(Transverser{}, *v.right); | ||
} | } | ||
else | |||
{ | { | ||
// !sizeof(T) | // The !sizeof(T) expression is always false | ||
static_assert(!sizeof(T), | static_assert(!sizeof(T), "non-exhaustive visitor!"); | ||
}; | }; | ||
} | } | ||
}; | }; | ||
/* | /*Tree forest = ...; | ||
std:: | std::visit(Transverser{}, forest);*/ | ||
</syntaxhighlight> | |||
== संलग्न संघों के रूप में वर्ग पदानुक्रम == | |||
[[ ऑब्जेक्ट ओरिएंटेड प्रोग्रामिंग |ऑब्जेक्ट-ओरिएंटेड प्रोग्रामिंग]] में विशिष्ट वर्ग पदानुक्रम में, प्रत्येक उपवर्ग उस वर्ग के लिए अद्वितीय डेटा को समाहित कर सकता है। आभासी विधि लुकअप करने के लिए उपयोग किया जाने वाला मेटाडेटा (उदाहरण के लिए, अधिकांश C++ कार्यान्वयन में ऑब्जेक्ट का [[आभासी विधि|वेटेबल]] सूचक) उपवर्ग की पहचान करता है और उदाहरण के द्वारा संग्रहीत विशेष डेटा की पहचान करने वाले संलग्न के रूप में प्रभावी ढंग से कार्य करता है ([[RTTI|आरटीटीआई (RTTI)]] देखें)। किसी ऑब्जेक्ट का निर्माता इस संलग्न को सेट करता है, और यह ऑब्जेक्ट के पूरे जीवनकाल में स्थिर रहता है। | |||
फिर भी, वर्ग पदानुक्रम में वास्तविक [[उपप्रकार बहुरूपता]] सम्मिलित होती है इसे उसी आधार प्रकार के और उपवर्ग बनाकर बढ़ाया जा सकता है, जिसे संलग्न/डिस्पैच मॉडल के तहत सही ढंग से नियंत्रित नहीं किया जा सकता है। इसलिए, प्रायः किसी सबऑब्जेक्ट के 'संलग्न' पर स्थिति विश्लेषण करना या प्रेषण करना संभव नहीं है जैसा कि संलग्न संघों के लिए होता है। स्काला जैसी कुछ भाषाएँ बेस वर्ग को "बंद" करने की अनुमति देती हैं, और संलग्न संघों को बंद बेस वर्ग के साथ एकीकृत करती हैं। | |||
फिर भी, | |||
== यह भी देखें == | == यह भी देखें == | ||
* | * विविक्तकर, [[कोरबा|सीओआरबीए (CORBA)]] में विभेदित संघों के लिए प्रकार संलग्न | ||
* [[वैरिएंट प्रकार (COM)]] | * [[वैरिएंट प्रकार (COM)|परिवर्ती प्रकार (COM)]] | ||
==संदर्भ== | ==संदर्भ== | ||
{{Reflist}} | {{Reflist}} | ||
== बाहरी संबंध == | == बाहरी संबंध == | ||
*[http://www.boost.org/libs/variant/index.html boost::variant] is a C++ typesafe discriminated union | *[http://www.boost.org/libs/variant/index.html boost::variant] is a C++ typesafe discriminated union | ||
Revision as of 19:58, 17 July 2023
कंप्यूटर विज्ञान में, संलग्न संघ, जिसे परिवर्ती, परिवर्ती रिकॉर्ड, चयन प्रकार, विभेदित संघ, असंयुक्त संघ, योग प्रकार या सहउत्पाद भी कहा जाता है, डेटा संरचना है जिसका उपयोग मान रखने के लिए किया जाता है जो कई अलग-अलग, लेकिन निश्चित, प्रकारों पर ले जा सकता है। किसी भी समय केवल एक ही प्रकार का उपयोग किया जा सकता है, और संलग्न क्षेत्र स्पष्ट रूप से इंगित करता है कि कौन सा प्रकार उपयोग में है। इसे एक ऐसे प्रकार के रूप में सोचा जा सकता है जिसमें कई "स्थितियां" होती हैं, जिनमें से प्रत्येक को उस प्रकार में युक्तियोजित किए जाने पर सही ढंग से संभाला जाना चाहिए। यह पुनरावर्ती डेटाटाइप को परिभाषित करने में महत्वपूर्ण है, जिसमें किसी मान के कुछ घटक का प्रकार उस मान के समान हो सकता है, उदाहरण के लिए ट्रीस का प्रतिनिधित्व करने के लिए एक प्रकार को परिभाषित करने में, जहां मल्टी-नोड सबट्रीस और लीव्स को अलग करना आवश्यक है। सामान्य संघों की तरह, संलग्न संघ प्रत्येक प्रकार के लिए स्टोरेज क्षेत्रों को ओवरलैप करके स्टोरेज बचा सकती हैं, क्योंकि एक समय में केवल एक ही उपयोग में होता है।
विवरण
एमएल (ML) और हास्केल जैसी कार्यात्मक प्रोग्रामिंग भाषाओं में संलग्न संघ सबसे महत्वपूर्ण हैं, जहां उन्हें डेटाप्रकार कहा जाता है (बीजगणितीय डेटा प्रकार देखें) और संकलक यह सत्यापित करने में सक्षम है कि संलग्न संघों की सभी स्थितियों को कई प्रकार की त्रुटियों से बचते हुए सदैव नियंत्रित किया जाता है। हालाँकि, इन्हें लगभग किसी भी प्रोग्रामिंग भाषा में बनाया जा सकता है, और अलग्न संघों की तुलना में अधिक सुरक्षित हैं, जिन्हें प्रायः संघ कहा जाता है, जो समान हैं लेकिन स्पष्ट रूप से ट्रैक नहीं करते हैं कि संघ का कौन सा सदस्य वर्तमान में उपयोग में है।
संलग्न संघों के साथ प्रायः एक प्रकार के निर्माता की अवधारणा जुड़ी होती है, जो वर्ग के लिए निर्माता के समान है लेकिन समान नहीं होता है। प्रारंभिक संलग्न प्रकार और संबंधित प्रकार को ध्यान में रखते हुए, प्रकार निर्माता संलग्न संघ प्रकार का उत्पादन करते हैं।
गणितीय रूप से, संलग्न संघ असंयुक्त या विभेदित संघों के अनुरूप होते हैं, जिन्हें प्रायः + का उपयोग करके लिखा जाता है। असंयुक्त संघ A + B के तत्व को देखते हुए, यह निर्धारित करना संभव है कि यह A या B से आया है या नहीं। यदि कोई तत्व दोनों में निहित है, तो A + B में मान की दो प्रभावी रूप से भिन्न प्रतियां होंगी, एक A से और एक B से।
प्रकार सिद्धांत में, संलग्न संघ को योग प्रकार कहा जाता है। योग प्रकार उत्पाद प्रकारों के द्वैत हैं। संकेतन अलग-अलग होते हैं, लेकिन प्रायः योग प्रकार A + B (अंतःक्षेपों) के लिए दो परिचय के साथ आता है- inj1: A → A + B और inj2: B → A + B। उन्मूलन रूप स्थिति विश्लेषण है, जिसे एमएल-शैली भाषाओं में पैटर्न मिलान के रूप में जाना जाता है- यदि e में प्रकार A + B है और e1 और e2 में क्रमशः x: A और y: B की मान्यताओं के तहत प्रकार है, तो शब्द में प्रकार है। योग प्रकार करी-हावर्ड समानता के तहत अंतर्ज्ञानवादी तार्किक विच्छेदन से मेल खाता है।
प्रगणित प्रकार को विकृत स्थिति के रूप में देखा जा सकता है- इकाई प्रकारों का संलग्न संघ है। यह अशक्त निर्माताओं के समुच्चय से मेल खाता है और इसे साधारण संंलग्न परिवर्ती के रूप में कार्यान्वित किया जा सकता है, क्योंकि इसमें संलग्न के मान के अलावा कोई अतिरिक्त डेटा नहीं है।
कई प्रोग्रामिंग तकनीक और डेटा संरचनाएं, जिनमें रोप, अनुयोगी मूल्यांकन, वर्ग पदानुक्रम (नीचे देखें), मनमानी-सटीक अंकगणित, सीडीआर (CDR) कोडिंग, अप्रत्यक्ष बिट और अन्य प्रकार के संलग्न संकेतों आदि सम्मिलित हैं, प्रायः कुछ प्रकार के संलग्न संघों का उपयोग करके कार्यान्वित किए जाते हैं।
संलग्न संघ को सबसे सरल प्रकार के स्व-वर्णन डेटा प्रारूप के रूप में देखा जा सकता है। संलग्न संघ के संलग्न को सबसे सरल प्रकार के मेटाडेटा के रूप में देखा जा सकता है।
लाभ और हानि
अलग्न संघ की तुलना में संलग्न संघ का प्राथमिक लाभ यह है कि सभी एक्सेस सुरक्षित हैं, और संकलक यह भी जांच सकता है कि सभी स्थितियों को संभाला गया है। अलग्न संघ वर्तमान में सक्रिय क्षेत्र की सही पहचान करने के लिए प्रोग्राम तर्क पर निर्भर करता हैं, जिसके परिणामस्वरूप अजीब व्यवहार हो सकता है और यदि वह तर्क विफल हो जाता है तो बग ढूंढना मुश्किल हो सकता है।
प्रत्येक प्रकार के लिए क्षेत्र वाले साधारण रिकॉर्ड की तुलना में संलग्न संघ का प्राथमिक लाभ यह है कि यह सभी प्रकार के लिए स्टोरेज को ओवरलैप करके स्टोरेज बचाता है। कुछ कार्यान्वयन सबसे बड़े प्रकार के लिए पर्याप्त स्टोरेज आरक्षित रखते हैं, जबकि अन्य आवश्यकतानुसार संलग्न संघ मान के आकार को गतिशील रूप से समायोजित करते हैं। जब मान अपरिवर्तनीय होता है, तो उतनी ही स्टोरेज आवंटित करना आसान होता है जितनी आवश्यकता होती है।
संलग्न संघों का मुख्य हानि यह है कि टैग स्थान घेरता है। चूँकि प्रायः बहुत कम संख्या में विकल्प होते हैं, संलग्न को प्रायः जहां भी स्थान मिलता है, 2 या 3 बिट्स में निष्पीडित किया जा सकता है, लेकिन कभी-कभी ये बिट्स भी उपलब्ध नहीं होते हैं। इस स्थिति में, सहायक विकल्प संलग्न को मोड़ना, गणना करना या एन्कोड करना हो सकता है, जहां संलग्न मान की गणना संंघ क्षेत्र की सामग्री से गतिशील रूप से की जाती है। इसके सामान्य उदाहरण आरक्षित मानों का उपयोग हैं, उदाहरण के लिए, सकारात्मक संख्या वापस लाने वाला फ़ंक्शन विफलता को इंगित करने के लिए -1 वापस कर सकता है, और प्रहरी मान, जो प्रायः संलग्न संकेतों में उपयोग किए जाते हैं।
कभी-कभी, अलग्न संघों का उपयोग प्रकारों के बीच बिट-स्तरीय रूपांतरण करने के लिए किया जाता है, जिन्हें सी++ (C++) में पुनः व्याख्या विक्षेप कहा जाता है। संलग्न संघ इस उद्देश्य के लिए अभिप्रेत नहीं हैं प्रायः जब भी संलग्न बदला जाता है तो एक नया मान निर्दिष्ट किया जाता है।
कई भाषाएँ, कुछ हद तक, सार्वभौमिक डेटा प्रकार का समर्थन करती हैं, जो एक ऐसा प्रकार है जिसमें प्रत्येक दूसरे प्रकार का प्रत्येक मान सम्मिलित होता है, और प्रायः सार्वभौमिक प्रकार के मान के वास्तविक प्रकार का परीक्षण करने का तरीका प्रदान किया जाता है। इन्हें कभी-कभी परिवर्ती के रूप में भी जाना जाता है। जबकि सार्वभौमिक डेटा प्रकार उनकी औपचारिक परिभाषा में संलग्न संघों के साथ तुलनीय हैं, विशिष्ट संलग्न संघों में अपेक्षाकृत कम संख्या में स्थितियां सम्मिलित होती हैं, और ये स्थितियां एकल सुसंगत अवधारणा को व्यक्त करने के विभिन्न तरीके बनाते हैं, जैसे डेटा संरचना नोड या निर्देश। साथ ही, यह भी अपेक्षा है कि संलग्न संघ का उपयोग किए जाने पर उसके प्रत्येक संभावित स्थिति से निपटा जाएगा। सार्वभौमिक डेटा प्रकार के मान संबंधित नहीं हैं और उन सभी से निपटने का कोई व्यवहार्य तरीका नहीं है।
विकल्प प्रकार और अपवाद प्रबंधन की तरह, संलग्न संघों का उपयोग कभी-कभी असाधारण परिणामों की घटना को संभालने के लिए किया जाता है। प्रायः इन संलग्नों को आरक्षित मानों के रूप में मोड़ दिया जाता है, और उनकी घटना की लगातार जांच नहीं की जाती है: यह प्रोग्रामिंग त्रुटियों का काफी सामान्य स्रोत है। संलग्न संघों के इस उपयोग को निम्नलिखित कार्यों के साथ मोनाड के रूप में औपचारिक रूप दिया जा सकता है-
जहां "मान" और "त्रुटि" संघ प्रकार के निर्माता हैं, A और B वैध परिणाम प्रकार हैं और E त्रुटि स्थितियों का प्रकार है। वैकल्पिक रूप से, उसी मोनाड को वापस और दो अतिरिक्त कार्यों, एफएमएपी (fmap) और संबद्ध द्वारा वर्णित किया जा सकता है-
उदाहरण
मान लें कि हम पूर्णांकों का बाइनरी ट्री बनाना चाहते थे। एमएल में, हम इस तरह डेटाप्रकार बनाकर ऐसा करेंगे-
datatype tree = Leaf
| Node of (int * tree * tree)
यह दो स्थितियों के साथ संलग्न संघ है- एक, लीफ, का उपयोग ट्री के पथ को समाप्त करने के लिए किया जाता है, और अनिवार्य भाषाओं में शून्य मान की तरह कार्य करता है। दूसरी शाखा में नोड होता है, जिसमें एक पूर्णांक और बाएं और दाएं सबट्री होता है। लीफ और नोड निर्माता हैं, जो हमें वास्तव में विशेष ट्री बनाने में सक्षम बनाते हैं, जैसे-
Node(5, Node(1, Leaf, Leaf), Node(3, Leaf, Node(4, Leaf, Leaf)))
जो इस ट्री के अनुरूप है-
अब हम आसानी से टाइपसेफ़ फ़ंक्शन लिख सकते हैं जो, मान लीजिए, ट्री में नोड्स की संख्या की गणना करता है-
fun countNodes(Leaf) = 0
| countNodes(Node(int, left, right)) =
1 + countNodes(left) + countNodes(right)
भाषा समर्थन की समयरेखा
1960s
एएलजीओएल (ALGOL) 68 में, संलग्न संघों को संयुक्त मोड कहा जाता है, संलग्न अंतर्निहित है, और case निर्माण का उपयोग यह निर्धारित करने के लिए किया जाता है कि कौन सा क्षेत्र संलग्न किया गया है-
mode node = union (real, int, compl, string);
node के union case के लिए उपयोग उदाहरण-
node n := "1234";
case n in
(real r): print(("real:", r)),
(int i): print(("int:", i)),
(compl c): print(("compl:", c)),
(string s): print(("string:", s))
out print(("?:", n))
esac
1970s और 1980s
हालाँकि मुख्य रूप से केवल कार्यात्मक प्रोग्रामिंग भाषाएँ जैसे एमएल (1970 के दशक से) और हास्केल (1990 के दशक से) संलग्न संघों को केंद्रीय भूमिका देती हैं और यह जाँचने की शक्ति रखती हैं कि सभी स्थितियों को संभाला जाता है, अन्य भाषाएँ भी संलग्न संघों का समर्थन करती हैं। हालाँकि, व्यवहार में वे कार्यात्मक भाषा संकलकों द्वारा सक्षम किए गए अनुकूलन के कारण गैर-कार्यात्मक भाषाओं में कम कुशल हो सकते हैं जो स्पष्ट संलग्न जांच को समाप्त कर सकते हैं और संलग्न के स्पष्ट स्टोरेज से बच सकते हैं।[citation needed]
पास्कल, एडा और मोडुला-2 उन्हें परिवर्ती रिकॉर्ड (एडा में औपचारिक रूप से विभेदित प्रकार) कहते हैं, और संलग्न क्षेत्र को मैन्युअल रूप से बनाने और संलग्न मान निर्दिष्ट करने की आवश्यकता होती है, जैसा कि इस पास्कल उदाहरण में है-
type shapeKind = (square, rectangle, circle);
shape = record
centerx : integer;
centery : integer;
case kind : shapeKind of
square : (side : integer);
rectangle : (width, height : integer);
circle : (radius : integer);
end;
और यह एडा समकक्ष हैं-
type Shape_Kind is (Square, Rectangle, Circle);
type Shape (Kind : Shape_Kind) is record
Center_X : Integer;
Center_Y : Integer;
case Kind is
when Square =>
Side : Integer;
when Rectangle =>
Width, Height : Integer;
when Circle =>
Radius : Integer;
end case;
end record;
-- Any attempt to access a member which existence depends
-- on a certain value of the discriminant, while the
-- discriminant is not the expected one, raises an error.
सी(C) और सी++ (C++) में, दृढ़ एक्सेस अनुशासन का उपयोग करके बिना संलग्न संघों से संलग्न संघ बनाया जा सकता है, जहां संलग्न की सदैव जांच की जाती है-
enum ShapeKind { Square, Rectangle, Circle };
struct Shape {
int centerx;
int centery;
enum ShapeKind kind;
union {
struct { int side; }; /* Square */
struct { int width, height; }; /* Rectangle */
struct { int radius; }; /* Circle */
};
};
int getSquareSide(struct Shape* s) {
assert(s->kind == Square);
return s->side;
}
void setSquareSide(struct Shape* s, int side) {
s->kind = Square;
s->side = side;
}
/* and so on */
जब तक संघ क्षेत्र को केवल फ़ंक्शंस के माध्यम से एक्सेस किया जाता है, तब तक एक्सेस सुरक्षित और सही रहेगा। एन्कोडेड संलग्न के लिए उसी दृष्टिकोण का उपयोग किया जा सकता है हम केवल संलग्न को डिकोड करते हैं और फिर प्रत्येक एक्सेस पर इसकी जांच करते हैं। यदि इन संलग्न जांचों की अक्षमता चिंता का विषय है, तो अंतिम संस्करण में उन्हें स्वचालित रूप से हटाया जा सकता है।
सी और सी++ में विशेष संलग्न संघ के लिए भाषा समर्थन भी है- संभवतः-शून्य सूचक। इसकी तुलना एमएल में option प्रकार या हास्केल में Maybe प्रकार से की जा सकती है, और इसे संलग्न सूचक के रूप में देखा जा सकता है- दो प्रकार का संलग्न संघ (एन्कोडेड संलग्न के साथ)-
- मान्य सूचक,
- केवल एक मान वाला शून्य सूचक प्रकार,
null, असाधारण स्थिति का संकेत देता है।
दुर्भाग्य से, सी संकलक यह सत्यापित नहीं करते हैं कि अशक्त स्थिति को सदैव संभाला जाता है, और यह सी कोड में त्रुटियों का विशेष रूप से प्रचलित स्रोत है, क्योंकि असाधारण स्थितियों को अनदेखा करने की प्रवृत्ति होती है।
2000s
सी की एक उन्नत बोली जिसे साइक्लोन कहा जाता है, में टैग किए गए संघों के लिए व्यापक अंतर्निहित समर्थन है।[1]
रस्ट, हेक्स और स्विफ्ट भाषाओं में एनम प्रकार संलग्न संघों के रूप में भी काम करते हैं।
बूस्ट सी++ लाइब्रेरीज़ की परिवर्ती लाइब्रेरी ने प्रदर्शित किया कि सी++ में लाइब्रेरी के रूप में सुरक्षित संलग्न संघ को कार्यान्वित करना संभव है, जिसे फ़ंक्शन ऑब्जेक्ट का उपयोग करके देखा जा सकता है।
struct display : boost::static_visitor<void>
{
void operator()(int i)
{
std::cout << "It's an int, with value " << i << std::endl;
}
void operator()(const std::string& s)
{
std::cout << "It's a string, with value " << s << std::endl;
}
};
boost::variant<int, std::string> v = 42;
boost::apply_visitor(display(), v);
boost::variant<int, std::string> v = "hello world";
boost::apply_visitor(display(), v);
स्काला में स्थिति वर्ग हैं-
sealed abstract class Tree
case object Leaf extends Tree
case class Node(value: Int, left: Tree, right: Tree) extends Tree
val tree = Node(5, Node(1, Leaf, Leaf), Node(3, Leaf, Node(4, Leaf, Leaf)))
क्योंकि वर्ग पदानुक्रम बंद कर दिया गया है, संकलक यह जांच सकता है कि सभी स्थितियों को पैटर्न मिलान में संभाला गया है-
tree match {
case Node(x, _, _) => println("top level node value: " + x)
case Leaf => println("top level node is a leaf")
}
स्काला स्थिति वर्ग उपप्रकार के माध्यम से पुन: उपयोग की अनुमति भी देते हैं-
sealed abstract class Shape(centerX: Int, centerY: Int)
case class Square(side: Int, centerX: Int, centerY: Int) extends Shape(centerX, centerY)
case class Rectangle(length: Int, height: Int, centerX: Int, centerY: Int) extends Shape(centerX, centerY)
case class Circle(radius: Int, centerX: Int, centerY: Int) extends Shape(centerX, centerY)
F# ने संघों के साथ विभेदीकृत किया है-
type Tree =
| Leaf
| Node of value: int * left: Tree * right: Tree
let tree = Node(5, Node(1, Leaf, Leaf), Node(3, Leaf, Node(4, Leaf, Leaf)))
क्योंकि परिभाषित स्थिति संपूर्ण हैं, संकलक यह जांच सकता है कि सभी स्थितियों को पैटर्न मिलान में नियंत्रित किया गया है-
match tree with
| Node (x, _, _) -> printfn "top level node value: %i" x
| Leaf -> printfn "top level node is a leaf"
हेक्स का एनम संलग्न संघों के रूप में भी काम करता हैं-[2]
enum Color {
Red;
Green;
Blue;
Rgb(r:Int, g:Int, b:Int);
}
इनका मिलान स्विच अभिव्यक्ति का उपयोग करके किया जा सकता है-
switch (color) {
case Red: trace("Color was red");
case Green: trace("Color was green");
case Blue: trace("Color was blue");
case Rgb(r, g, b): trace("Color had a red value of " +r);
}
निम के पास पास्कल और एडा की घोषणा के समान ऑब्जेक्ट परिवर्ती[3] हैं-
type
ShapeKind = enum
skSquare, skRectangle, skCircle
Shape = object
centerX, centerY: int
case kind: ShapeKind
of skSquare:
side: int
of skRectangle:
length, height: int
of skCircle:
radius: int
मैक्रोज़ का उपयोग पैटर्न मिलान का अनुकरण करने या ऑब्जेक्ट परिवर्ती घोषित करने के लिए सिंटैक्टिक शुगर बनाने के लिए किया जा सकता है, जिसे यहां पैकेज पैटी द्वारा कार्यान्वित किया गया है-
import patty
proc `~`[A](a: A): ref A =
new(result)
result[] = a
variant List[A]:
Nil
Cons(x: A, xs: ref List[A])
proc listHelper[A](xs: seq[A]): List[A] =
if xs.len == 0: Nil[A]()
else: Cons(xs[0], ~listHelper(xs[1 .. xs.high]))
proc list[A](xs: varargs[A]): List[A] = listHelper(@xs)
proc sum(xs: List[int]): int = (block:
match xs:
Nil: 0
Cons(y, ys): y + sum(ys[])
)
echo sum(list(1, 2, 3, 4, 5))
2010s
स्काला 3 में एनम्स जोड़े गए हैं,[4] जिससे हमें पहले के स्काला उदाहरणों को अधिक संक्षेप में फिर से लिखने की अनुमति मिलती है-
enum Tree[+T]:
case Leaf
case Node(x: Int, left: Tree[T], right: Tree[T])
enum Shape(centerX: Int, centerY: Int):
case Square(side: Int, centerX: Int, centerY: Int) extends Shape(centerY, centerX)
case Rectangle(length: Int, height: Int, centerX: Int, centerY: Int) extends Shape(centerX, centerY)
case Circle(radius: Int, centerX: Int, centerY: Int) extends Shape(centerX, centerY)
रस्ट भाषा को संलग्न संघों, जिन्हें एनम्स कहा जाता है, के लिए व्यापक समर्थन प्राप्त है।[5] उदाहरण के लिए-
enum Tree {
Leaf,
Node(i64, Box<Tree>, Box<Tree>)
}
यह संघों पर मिलान की भी अनुमति देता है-
let tree = Tree::Node(
2,
Box::new(Tree::Node(0, Box::new(Tree::Leaf), Box::new(Tree::Leaf))),
Box::new(Tree::Node(3, Box::new(Tree::Leaf),
Box::new(Tree::Node(4, Box::new(Tree::Leaf), Box::new(Tree::Leaf)))))
);
fn add_values(tree: Tree) -> i64 {
match tree {
Tree::Node(v, a, b) => v + add_values(*a) + add_values(*b),
Tree::Leaf => 0
}
}
assert_eq!(add_values(tree), 9);
रस्ट का त्रुटि प्रबंधन मॉडल बड़े पैमाने पर इन संंलग्न संघों पर निर्भर करता है, विशेष रूप से Option<T> प्रकार, जो या तो None या Some(T) है, और Result<T, E> प्रकार, जो या तो Ok(T) या Err(E) है।[6]
गणनाओं के माध्यम से संलग्न संघों के लिए स्विफ्ट को भी पर्याप्त समर्थन प्राप्त है।[7] उदाहरण के लिए-
enum Tree {
case leaf
indirect case node(Int, Tree, Tree)
}
let tree = Tree.node(
2,
.node(0, .leaf, .leaf),
.node(3, .leaf, .node(4, .leaf, .leaf))
)
func add_values(_ tree: Tree) -> Int {
switch tree {
case let .node(v, a, b):
return v + add_values(a) + add_values(b)
case .leaf:
return 0
}
}
assert(add_values(tree) == 9)
टाइपस्क्रिप्ट के साथ संलग्न संघ बनाना भी संभव है। उदाहरण के लिए-
interface Leaf { kind: "leaf"; }
interface Node { kind: "node"; value: number; left: Tree; right: Tree; }
type Tree = Leaf | Node
const root: Tree = {
kind: "node",
value: 5,
left: {
kind: "node",
value: 1,
left: { kind: "leaf" },
right: { kind: "leaf" }
},
right: {
kind: "node",
value: 3,
left: { kind: "leaf" },
right: {
kind: "node",
value: 4,
left: { kind: "leaf" },
right: { kind: "leaf" }
}
}
}
function visit(tree: Tree) {
switch (tree.kind) {
case "leaf":
break
case "node":
console.log(tree.value)
visit(tree.left)
visit(tree.right)
break
}
}
पायथन 3.9 एनोटेशन टाइपिंग के लिए समर्थन प्रस्तुत करता है जिसका उपयोग संलग्न संघ प्रकार (पीईपी-593[8]) को परिभाषित करने के लिए किया जा सकता है-
Currency = Annotated[
TypedDict('Currency', {'dollars': float, 'pounds': float}, total=False),
TaggedUnion,
]
C++17 std::variant और constexpr if का परिचय देता है
using Tree = std::variant<struct Leaf, struct Node>;
struct Leaf
{
std::string value;
};
struct Node
{
Tree* left = nullptr;
Tree* right = nullptr;
};
struct Transverser
{
template<typename T>
void operator()(T&& v)
{
if constexpr (std::is_same_v<T, Leaf&>)
{
std::cout << v.value << "\n";
}
else if constexpr (std::is_same_v<T, Node&>)
{
if (v.left != nullptr)
std::visit(Transverser{}, *v.left);
if (v.right != nullptr)
std::visit(Transverser{}, *v.right);
}
else
{
// The !sizeof(T) expression is always false
static_assert(!sizeof(T), "non-exhaustive visitor!");
};
}
};
/*Tree forest = ...;
std::visit(Transverser{}, forest);*/
संलग्न संघों के रूप में वर्ग पदानुक्रम
ऑब्जेक्ट-ओरिएंटेड प्रोग्रामिंग में विशिष्ट वर्ग पदानुक्रम में, प्रत्येक उपवर्ग उस वर्ग के लिए अद्वितीय डेटा को समाहित कर सकता है। आभासी विधि लुकअप करने के लिए उपयोग किया जाने वाला मेटाडेटा (उदाहरण के लिए, अधिकांश C++ कार्यान्वयन में ऑब्जेक्ट का वेटेबल सूचक) उपवर्ग की पहचान करता है और उदाहरण के द्वारा संग्रहीत विशेष डेटा की पहचान करने वाले संलग्न के रूप में प्रभावी ढंग से कार्य करता है (आरटीटीआई (RTTI) देखें)। किसी ऑब्जेक्ट का निर्माता इस संलग्न को सेट करता है, और यह ऑब्जेक्ट के पूरे जीवनकाल में स्थिर रहता है।
फिर भी, वर्ग पदानुक्रम में वास्तविक उपप्रकार बहुरूपता सम्मिलित होती है इसे उसी आधार प्रकार के और उपवर्ग बनाकर बढ़ाया जा सकता है, जिसे संलग्न/डिस्पैच मॉडल के तहत सही ढंग से नियंत्रित नहीं किया जा सकता है। इसलिए, प्रायः किसी सबऑब्जेक्ट के 'संलग्न' पर स्थिति विश्लेषण करना या प्रेषण करना संभव नहीं है जैसा कि संलग्न संघों के लिए होता है। स्काला जैसी कुछ भाषाएँ बेस वर्ग को "बंद" करने की अनुमति देती हैं, और संलग्न संघों को बंद बेस वर्ग के साथ एकीकृत करती हैं।
यह भी देखें
- विविक्तकर, सीओआरबीए (CORBA) में विभेदित संघों के लिए प्रकार संलग्न
- परिवर्ती प्रकार (COM)
संदर्भ
- ↑ "Cyclone: Tagged Unions".
- ↑ "एनम्स का उपयोग करना - हेक्स - क्रॉस-प्लेटफ़ॉर्म टूलकिट". Haxe Foundation.
- ↑ "निम मैनुअल". nim-lang.org. Retrieved 2020-01-23.
- ↑ "Scala 3 Language Reference: Enumerations". The Scala Team.
- ↑ "जंग प्रोग्रामिंग भाषा". Mozilla.
- ↑ "उदाहरण के द्वारा जंग". Mozilla.
- ↑ "Enumerations — The Swift Programming Language (Swift 5.4)". docs.swift.org. Retrieved 2021-04-28.
- ↑ "PEP 593 -- Flexible function and variable annotations". Python.org (in English). Retrieved 2021-06-20.
बाहरी संबंध
- boost::variant is a C++ typesafe discriminated union
- std.variant is an implementation of variant type in D 2.0