Кіріспе
Бірнеше түрлі, бірақ белгілі бір типтерді қабылдай алатын мәнді сақтауға арналған дерек құрылымы. Компьютер ғылымында, таңбаланған одақ, сондай-ақ вариант, вариант жазбасы, таңдау типі, кемсітілген одақ, ажыратылған одақ, қосынды типі немесе копродукт деп аталады. Кез келген уақытта тек бір тип қолданылады, ал таңбалау өрісі қолданылып жатқан типті нақты көрсетеді. Бұл типті бірнеше "жағдайлары" бар ретінде қарастыруға болады, олардың әрқайсысы осы типпен жұмыс істегенде дұрыс өңделуі тиіс. Бұл рекурсивті дерек типтерін анықтау үшін маңызды, онда мәннің кейбір бөліктері сол мәнмен бірдей типке ие болуы мүмкін, мысалы, ағаштарды бейнелеу үшін типті анықтағанда, көп түйінді кіші ағаштар мен жапырақтарды ажырату қажет. Қарапайым одақтар сияқты, таңбаланған одақтар әр тип үшін жад аймақтарын үнемдеуге мүмкіндік береді, өйткені бір уақытта тек біреуі ғана қолданылады.
In computer science, a tagged union, also called a variant, variant record, choice type, discriminated union, disjoint union, sum type, or coproduct, is a data structure used to hold a value that could take on several different, but fixed, types. Only one of the types can be in use at any one time, and a tag field explicitly indicates which type is in use. It can be thought of as a type that has several "cases", each of which should be handled correctly when that type is manipulated. This is critical in defining recursive datatypes, in which some component of a value may have the same type as that value, for example in defining a type for representing trees, where it is necessary to distinguish multi node subtrees and leaves. Like ordinary unions, tagged unions can save storage by overlapping storage areas for each type, since only one is in use at a time.
Сипаттама
Тегтелген одақтар ML және Haskell сияқты функционалдық бағдарламалау тілдерінде ең маңызды, онда олар дерек түрлері деп аталады (алгебралық дерек түрін қараңыз), ал компилятор тегтелген одақтың барлық жағдайлары міндетті түрде өңделетінін тексеріп, көптеген қателерден сақтай алады. Компиляция уақытында тексерілген сома түрлері де Rust-те кеңінен қолданылады, онда олар enum деп аталады. Дегенмен, оларды кез келген бағдарламалау тілінде құрастыруға болады және олар тегтелмеген одақтардан (көбінесе одақтар деп аталады) әлдеқайда қауіпсіз, себебі тегтелмеген одақтар ұқсас болғанымен, одақтың қандай мүшесі қолданылып жатқанын нақты қадағаламайды. Тегтелген одақтар көбінесе конструктор ұғымымен бірге келеді, ол сынып конструкторынан өзгеше болғанымен, оған ұқсас. Конструктор – бұл белгісі мен сәйкес типтің мәні берілгенде, тегтелген одақ түрінің мәнін шығаратын функция немесе өрнек. Математикалық тұрғыдан алғанда, тегтелген одақтар бірікпеген немесе кемсітілген одақтарға сәйкес келеді, олар әдетте + белгісімен жазылады. Егер A + B бірікпеген одағының бір элементі берілсе, оның A-дан немесе B-ден келгенін анықтау мүмкін. Егер элемент екеуінде де болса, A + B-дегі мәннің екі нақтырақ көшірмесі болады – біреуі A-дан, екіншісі B-дан. Типтер теориясында тегтелген одақ сома типі деп аталады. Сома типтері өнім типтеріне қарама-қарсы болып табылады. Жазу тәсілдері әртүрлі болуы мүмкін, бірақ әдетте A + B сома типі екі енгізу формасымен (инъекциялар) бірге келеді: inj1: A → A + B және жою формасы – ML стильді тілдеріндегі үлгіге сәйкестік деп аталатын кейс-талдау: егер e-нің типі A + B болса және e1 мен e2 тиісінше x: A және y: B болжамдары бойынша типке ие болса, онда терминнің типі болады. Саналған типті дегенеративті жағдай ретінде қарастыруға болады: бірлік типтерінің тегтелген одағы. Бұл нөлдік конструкторлар жиынтығына сәйкес келеді және тегтің мәнінен басқа қосымша деректерді сақтамайтындықтан, қарапайым тегтік айнымалы ретінде жүзеге асырылуы мүмкін. Көптеген бағдарламалау техникалары мен дерек құрылымдары, соның ішінде арқан, жалқау бағалау, сыныптық иерархия (төменде қараңыз), кез келген дәлдіктегі арифметика, CDR кодтау, жанама бит және басқа да тегтелген сілтемелер, әдетте, тегтелген одақтың бір түрін қолдана отырып жүзеге асырылады. Тегтелген одақты өзін-өзі сипаттайтын дерек форматының ең қарапайым түрі ретінде қарастыруға болады. Тегтелген одақтың тегін метадеректердің ең қарапайым түрі ретінде қарастыруға болады.
Артықшылықтары мен кемшіліктері
Тагталған одақтың белгісіз одаққа қарағанда басты артықшылығы – барлық қолжетімділіктер қауіпсіз, ал компилятор тіпті барлық жағдайларды тексеріп отыра алады. Белгісіз одақтар қазіргі белсенді өрісті дұрыс анықтау үшін бағдарлама логикасына тәуелді, бұл логика сәтсіз болса, ерекше мінез-құлық пен қателерді табу қиынға соғады. Тагталған одақтың әрбір тип үшін жеке өріс бар қарапайым жазбаға қарағанда негізгі артықшылығы – ол барлық типтер үшін жадты үнемдеу арқылы жадты тиімді пайдаланады. Кейбір жүзеге асырулар ең үлкен типке жеткілікті жадты бөледі, ал басқалары тагталған одақ мәнінің көлемін қажеттілікке қарай динамикалық түрде реттейді. Егер мән өзгермейтін болса, қажетті көлемде жадты бөлу оңай. Тагталған одақтың басты кемшілігі – тақтың жадты алуы. Әдетте баламалардың саны аз болғандықтан, тақты жиі 2 немесе 3 битке сығып алуға болады, бірақ кейде тіпті бұл биттер қолжетімді емес. Бұл жағдайда пайдалы балама – бүктелген, есептелген немесе кодталған тагтар болуы мүмкін, онда таг мәні одақ өрісінің мазмұнынан динамикалық түрде есептеледі. Көбінесе резервтелген мәндерді пайдалану кездеседі, мысалы, оң санды қайтаратын функция қателіктерді көрсету үшін 1 қайтара алады, сондай-ақ таңбаланған көрсеткіштерінде қолданылатын күзетші мәндер. Кейде белгісіз одақтар типтер арасындағы бит деңгейіндегі түрлендірулерді орындау үшін қолданылады, оларды C++-та қайта түсіндіру құймалары деп атайды. Тагталған одақтар осы мақсат үшін арналмаған; әдетте, таг өзгерген сайын жаңа мән беріледі. Көптеген тілдер белгілі бір дәрежеде әмбебап дерек типін қолдайды, бұл әр түрлі типтің барлық мәндерін қамтитын тип және көбінесе әмбебап типтің мәнінің нақты типін тексерудің тәсілі ұсынылады. Бұларды кейде варианттар деп атайды. әмбебап деректер типтері олардың формальды анықтамасы бойынша тагталған одақтарға ұқсас болса да, әдеттегі тагталған одақтар салыстырмалы түрде аз сандағы жағдайларды қамтиды және бұл жағдайлар дерек құрылымы торабы немесе нұсқау сияқты бір тұтас ұғымды білдірудің әртүрлі жолдарын құрайды. Сонымен қатар, таңбаланған одақтың барлық мүмкін жағдайлары оны қолданған кезде қарастырылады деп күтілуде. әмбебап деректер типінің мәндері өзара байланысты емес және олардың барлығын қараудың мүмкін жолы жоқ. Опция типтері мен ерекшеліктерді өңдеу сияқты, таңбаланған одақтар кейде ерекше нәтижелердің пайда болуын басқару үшін қолданылады. Көбінесе бұл тагтар типке резервтелген мәндер ретінде бүктеледі және олардың пайда болуы үнемі тексерілмейді: бұл бағдарламалау қателерінің өте жиі кездесетін себебі. Тагталған одақтарды пайдалануды мынадай функциялармен монода ретінде формальдауға болады: мұнда "value" және "err" одақ типінің конструкторлары, A және B жарамды нәтижелер типтері және E қателік жағдайларының типі. Сонымен қатар, бір монадты return және fmap және join деген қосымша екі функция арқылы сипаттауға болады:
where "value" and "err" are the constructors of the union type, A and B are valid result types and E is the type of error conditions. Alternately, the same monad may be described by return and two additional functions, fmap and join:
Таңбаланған одақтардағы сыныптық иерархиялар
Объектіге бағытталған бағдарламалаудағы әдеттегі сынып иерархиясында әрбір кіші сынып сол сыныпқа ғана тән деректерді қоршауға алады. Виртуалды әдістерді іздеу үшін қолданылатын метадеректер (мысалы, көптеген C++ іске асыруларындағы объектінің vtable көрсеткіші) кіші сыныпты анықтайды және деректерді сақтаған мысалдың белгісі ретінде тиімді жұмыс істейді (RTTI қараңыз). Объектінің конструкторы осы белгіні орнатады және ол объектінің өмір бойында өзгермейді. Дегенмен, сынып иерархиясы нағыз кіші тип полиморфизмін қамтиды. Оны бірнеше кіші сыныптарды бірдей базалық типтен тудыру арқылы кеңейтуге болады, бұл белгі/жіберу үлгісімен дұрыс жұмыс істемейді. Сондықтан, кіші объектінің "белгісін" таңбаланған жиынтардағыдай талдау немесе жіберу әдетте мүмкін емес. Кейбір тілдер, мысалы Scala, базалық сыныптарды "мөрленген" деп белгілеуге мүмкіндік береді және таңбаланған жиынтарды мөрленген базалық сыныптармен біріктіреді.