Discriminated unions v C++

Re:Discriminated unions v C++
« Odpověď #15 kdy: 24. 10. 2020, 21:51:08 »

No, zdá se mi, že jsi si nepřečetl pořádně otázku. Podle té má mít typ Currency další dvě varianty,

Kód: [Vybrat]
Another of (currencyName : string) * decimal
| None

které se ale v toUSD nepoužijí (není to úplná funkce). Vyřešil jsi tedy jinou otázku.


Asi si nevšimol, že kód v #5 som nepísal ja, ale niekto iný. Ja som iba nahradil jednu klasickú konštrukciu konštrukciou, ktorá má kompaktnejší zápis. Funguje iba od C++17, nie je úplne všeobecná, ale v tejto forme mi vyhovuje a dá sa bez problémov používať.

Moja odpoveď by vyzerala asi takto:

Pre jednotlivé meny silné typy; u variantu zabudni na indexy a používaj visit overload pattern.

Ja by som naozaj žiadny kód nepísal.

Pod odpoveď #5 by som sa ale bez problému podpísal, pretože obsahuje všetko, čo je nutné a dá sa aj preložiť.


spíš tě chválím, že jsi své odpovědi #6 a #7 vynechal ze seznamu těch, u kterých tvrdíš, že porozuměly zadání.


To si láskavo nechaj pre niekoho iného, ja na to naozaj nie som vôbec zvedavý. Nemyslím si totiž, že niekto, kto odpoveď s riešením zásadného problému s vynechaním marginálnych a triviálnych záležitostí, považuje za odpoveď na úplne inú otázku, má nárok rozdeľovať nejaké pochvaly, zvlášť v kontexte ako to robíš ty. Nehovoriac o tom, že v C++ neprogramuješ a pochybujem, že tomu kódu rozumieš, vrátane toho, do akej miery sú tie vynechané veci triviálne alebo prečo sú vynechané.

Ale na doplňujúcu otázku ti odpoviem. Do funkcie by boli triviálnym spôsobom pridané chýbajúce veci a bol by samozrejme zmenený návratový typ na niektorú z podmienených foriem, čo je legitímna a často používaná technika. Čiste z C++ je použiteľný buď std::optional, alebo iné podobné alternatívy, alebo triedy použiteľné na ošetrenie chýb, či už z boostu alebo z návrhov pre ISO. Veľmi dobre použiteľný môže byť dokonca opäť std::variant, kde v prípade úspechu bude číselný typ použiteľný pre finančné operácie a v prípade neúspechu bude už spomenutý std::monostate alebo trieda s detailami k chybe.

Záleží iba na tom, ako chce používateľ pracovať s ošetrením chybových stavov, či ich chce riešiť na mieste, kde chyba vnikla alebo na nejakom mieste, kde chyby centrálne spravuje, napríklad blízko výstupu, alebo či to chce riešiť už ošetrením vstupov, aby nenastalo volanie s argumentom, ktorý nezaručuje výsledok.

Po konverzii prvotnej kolekcie obsahujúcej hodnoty v jednotlivých menách potom vznikne kolekcia výsledných variantov a pri ich redukcii na číselný súčet alebo na chybové hlásenie sa zas môže použiť visit overload pattern.

To všetko je však naozaj úplne iná otázka, súvisí s architektúrou a sem to vôbec nepatrí. Ale hlavne, pôvodca otázky prichádza z funkcionálneho sveta a toto je mu známe. Ako sa môžeš dočítať v jeho odpovedi.


Re:Discriminated unions v C++
« Odpověď #16 kdy: 24. 10. 2020, 22:42:39 »

tamten trailing return ze čtvrtýho řádku
Kód: [Vybrat]
template<class... Ts> overload(Ts...) -> overload<Ts...>;

neni v c++20 potřeba protože tam std::visit jakoby umí správně uhádnout návratovej typ a nemusí se mu radit hele :) ;)


Pekné, vyskúšam, uvidím. Som ale stále na C++17 a to mám ešte šťastie.


účelu týdletý template z řádků 18-21
Kód: [Vybrat]
template<CurrencyTag... Tags>
using CurrencyVariant = std::variant<CurrencyType<Tags>...>;

using Currency = CurrencyVariant<CurrencyTag::Eur, CurrencyTag::Usd, CurrencyTag::Btc>;
nerozumim ale mam takovej pocit žeje bezpečný ji min pro c++20 nahradit takle jednoduše :o :o

Kód: [Vybrat]
using Currency = std::variant<CurrencyTag::Eur, CurrencyTag::Usd, CurrencyTag::Btc>;


Na pocity v C++ funguje prekladač...

táákže výslednej upravenej zdrojáček takle nějak

Kód: [Vybrat]
#include <variant>

template<class... Ts> struct overload : Ts... { using Ts::operator()...; };

enum class CurrencyTag {
    Eur,
    Usd,
    Btc   
};

template<CurrencyTag Tag>
struct CurrencyType {
    double value;
};

using Currency = std::variant<CurrencyTag::Eur, CurrencyTag::Usd, CurrencyTag::Btc>;

constexpr double EUR_TO_USD = 1/1.1;
constexpr double BTC_TO_USD = 12000.;

constexpr double toUsd(const Currency &currency) {
    return std::visit(overload {
[](const CurrencyType<CurrencyTag::Eur>& currency) { return currency.value * EUR_TO_USD; },
[](const CurrencyType<CurrencyTag::Usd>& currency) { return currency.value; },
[](const CurrencyType<CurrencyTag::Btc>& currency) { return currency.value * BTC_TO_USD; }
    },
    currency);
}

int main() {
    static_assert(toUsd(CurrencyType<CurrencyTag::Btc>{1.}) == BTC_TO_USD);
    return 0;
}


...ktorý si asi nepoužil, pretože by si vedel, že tam máš chyby. A teraz čo s tým?

a samozdřejmě to de furt postaru overloadingem/přetěžováním jakože bez použití lambda funkcí variadic templates hele std::variant hele a visitoru takle nadivoko :D ;D ;D ;)
Kód: [Vybrat]
#include <iostream>

enum class CurrencyTag {
    Dolary,
    Tolary,
    Rubly   
};

template<CurrencyTag Tag>
struct CurrencyType {
    double value;
};

constexpr double TOLARY_TO_DOLARY = 123.456;
constexpr double RUBLY_TO_DOLARY = 0.0001;

constexpr double toUSD(const CurrencyType<CurrencyTag::Dolary> & platidlo){return platidlo.value;}
constexpr double toUSD(const CurrencyType<CurrencyTag::Tolary> & platidlo){return platidlo.value * TOLARY_TO_DOLARY;}
constexpr double toUSD(const CurrencyType<CurrencyTag::Rubly> & platidlo){return platidlo.value * RUBLY_TO_DOLARY;}

int main()
{
    CurrencyType<CurrencyTag::Tolary> hrnecPlnejTolaru = {5};
    CurrencyType<CurrencyTag::Rubly> cenaVodky = {1};
    std::cout << toUSD(hrnecPlnejTolaru) << std::endl;
    std::cout << toUSD(cenaVodky) << std::endl;
    return 0;
}

von už si to kompilátor jakoby nějak rozumě přežvejkne :D ;D ;) ;)


Toto už je asi iba doplnok k spracovaniu a s touto otázkou, ktorej témou je sumárny typ, teda v C++ variant, to nijako nesúvisí, keďže si ten variant vymazal. Zvlášť, keď potrebuješ v jednom kontajneri držať položky rôznych typov.

Re:Discriminated unions v C++
« Odpověď #17 kdy: 25. 10. 2020, 08:44:41 »
...To si láskavo nechaj pre niekoho iného, ja na to naozaj nie som vôbec zvedavý. Nemyslím si totiž, že niekto, kto odpoveď s riešením zásadného problému s vynechaním marginálnych a triviálnych záležitostí, považuje za odpoveď na úplne inú otázku, má nárok rozdeľovať nejaké pochvaly...

Rozdělovat pochvaly jsi začal ty, proto ta jízlivost ode mě (skutečně asi trochu přehnaná). Já bych se taky mohl urazit, že jsi nepochválil mojí odpověď, která uváděla na pravou míru tazatelovu domněnku, že std::variant neumožňuje víc variant stejného typu. Umožňuje (https://stackoverflow.com/a/43116041/3220468), a je to zásadní vlastnost součtového typu, která se v jazycích s first-class podporou součtového typu zcela běžně používá. Bohužel, v C++ praxi se zdá, že takový std::variant je natolik nepraktický na používání, že je lepší ty typy nějak odlišit (tagování, wrapnutí).

xyz

  • ***
  • 200
    • Zobrazit profil
Re:Discriminated unions v C++
« Odpověď #18 kdy: 25. 10. 2020, 10:40:43 »
<flame/>Cela diskuze mi pripomina snahu pouzivat co nejobskurnejsi a nejmene zname vlastnosti z daneho jazyka. A chudaci programatori, kteri potom maji takovy kod prebrat a nedejboze upravovat.

Re:Discriminated unions v C++
« Odpověď #19 kdy: 25. 10. 2020, 14:18:13 »



účelu týdletý template z řádků 18-21
Kód: [Vybrat]
template<CurrencyTag... Tags>
using CurrencyVariant = std::variant<CurrencyType<Tags>...>;

using Currency = CurrencyVariant<CurrencyTag::Eur, CurrencyTag::Usd, CurrencyTag::Btc>;
nerozumim ale mam takovej pocit žeje bezpečný ji min pro c++20 nahradit takle jednoduše :o :o

Kód: [Vybrat]
using Currency = std::variant<CurrencyTag::Eur, CurrencyTag::Usd, CurrencyTag::Btc>;


Na pocity v C++ funguje prekladač...

táákže výslednej upravenej zdrojáček takle nějak

Kód: [Vybrat]
#include <variant>

template<class... Ts> struct overload : Ts... { using Ts::operator()...; };

enum class CurrencyTag {
    Eur,
    Usd,
    Btc   
};

template<CurrencyTag Tag>
struct CurrencyType {
    double value;
};

using Currency = std::variant<CurrencyTag::Eur, CurrencyTag::Usd, CurrencyTag::Btc>;

constexpr double EUR_TO_USD = 1/1.1;
constexpr double BTC_TO_USD = 12000.;

constexpr double toUsd(const Currency &currency) {
    return std::visit(overload {
[](const CurrencyType<CurrencyTag::Eur>& currency) { return currency.value * EUR_TO_USD; },
[](const CurrencyType<CurrencyTag::Usd>& currency) { return currency.value; },
[](const CurrencyType<CurrencyTag::Btc>& currency) { return currency.value * BTC_TO_USD; }
    },
    currency);
}

int main() {
    static_assert(toUsd(CurrencyType<CurrencyTag::Btc>{1.}) == BTC_TO_USD);
    return 0;
}


...ktorý si asi nepoužil, pretože by si vedel, že tam máš chyby. A teraz čo s tým?
jejda :D

nj máš pravdu jeto rozbitý :o :o :-\ :-\
určitě sem to včera zkoušela ale asi sem jakoby zkompilovala něco uplně jinýho misto toho nebo nevim :o :o

a čože stým teraz?? ty template se de skutečně +- zbavit když tamto currency uděláš jako
Kód: [Vybrat]
using Currency = std::variant<CurrencyType<CurrencyTag::Eur>, CurrencyType<CurrencyTag::Usd>, CurrencyType<CurrencyTag::Btc>>;
ale nefunguje to když je současně umazanej ten trailing na čtvrtým řádku :o :o
kompilovaný v g++ 10.2.0 s parametrem -std=c++20


von už si to kompilátor jakoby nějak rozumě přežvejkne :D ;D ;) ;)


Toto už je asi iba doplnok k spracovaniu a s touto otázkou, ktorej témou je sumárny typ, teda v C++ variant, to nijako nesúvisí, keďže si ten variant vymazal. Zvlášť, keď potrebuješ v jednom kontajneri držať položky rôznych typov.
nóó ale mam takovej pocit že logika toho zdrojáčku je +- stejná tomu co po nás jako bylo požadovaný :) ;)
a vubec mam dojem že todleto std::variant de vobecně nahradit přetěžováním + jinejma už zavedenejma mechanizmama. nóó ale třeba se zase pletu ;D ;D ;) ;)
lidi postižený environmentálním žalem hele choděj za ekopsycholožkama hele 🤡 💆 🤡 💆


Re:Discriminated unions v C++
« Odpověď #20 kdy: 25. 10. 2020, 14:27:30 »
<flame/>Cela diskuze mi pripomina snahu pouzivat co nejobskurnejsi a nejmene zname vlastnosti z daneho jazyka. A chudaci programatori, kteri potom maji takovy kod prebrat a nedejboze upravovat.
si zato mužou sami že chtěli programovat v c++  ;D ;D ;) ;)

tamto hodně nový c++ trošičku vypadá jako když pejsek s kočičkou pekli dort. lidi co vyvýjej c++ si asi jako myslej že když tam nastrkaj všechny nejrůznější vychytávky s jinejch jazyků co kde jako viděli takže jakoby udělaj jazyk pro masy nóó ale myslim si že to dopadne uplně vobráceně a lidi se jim nato vykašlou. jedinej důvod proč se tendleten jazyk učim je už zmiňovanej unrealengine jinak nic. a i v tom unrealenginu de mastit různý ty blueprinty a naklikávat si všecko v gui takže to pro c++ nevidim moc dobře :o :o ??? :)
lidi postižený environmentálním žalem hele choděj za ekopsycholožkama hele 🤡 💆 🤡 💆

Re:Discriminated unions v C++
« Odpověď #21 kdy: 25. 10. 2020, 15:20:40 »
Konečne som sa zase dostal k C++ idem si teda prejsť aj Vaše odpovede a vyskúšam príklady čo ste sem poslali. Minule tu niekto písal že typ variant môže uložiť aj hodnoty rovnakého typu a mal pravdu (takže to čo som napísal v prvom poste že variant nemôže obsahovať rovnaký typ bol omyl spôsobený mojou nepozornosťou). Takže pomocou typu variant sa dajú nasimulovať aj discriminated unions. Včera v noci som to skúšal. Ako ste tu spomínali pattern matching síce C++ nemá, ale nahradil som ho obyčajným switchom a ten prvý príklad som prepísal takto: https://pastebin.com/CFykWbWQ resp aj nižšie, ale na pastebin je syntax highlighter, takže sa to lepšie číta.

Kód: [Vybrat]
#include <iostream>
#include <variant>
#include <vector>
#include <map>
#include <algorithm>
#include <iterator>

// operator pre vypisani mapy
template <typename K, typename V>
std::ostream& operator<<(std::ostream& out, const std::map<K, V>& vec)
{
out << "vector<T>[";
auto delimiter = false;
for (const auto& item : vec)
{
if (delimiter = true)
{
out << ", ";
}
out << item.first << ": " << item.second;
}
out << "]";
return out;
}

const auto usdEurCourse = 1.19;
const auto usdBtcCourse = 0.000076;

typedef std::tuple<std::string, double> AnotherTuple;

typedef std::variant<
/*USD*/ double,
/*EUR*/ double,
/*BTC*/ double,
/*Another*/ AnotherTuple
> currency;

enum
{
USD,
EUR,
BTC,
Another
};

auto comodityMarketsValues = std::map<std::string, currency>{
{ "Gold", currency{ std::in_place_index<USD>, 5.75 } },
{ "Platinium DAX", currency{ std::in_place_index<EUR>, 5.23 } },
//{ "FSTE Oil", currency{ std::in_place_index<Another>, AnotherTuple{ "GBP", 1023.22 } } },
};

double toUSD(currency curr)
{
switch (curr.index())
{
case USD: return std::get<USD>(curr);
case EUR: return std::get<EUR>(curr) * usdEurCourse;
case BTC: return std::get<BTC>(curr) * usdBtcCourse;
default: throw std::runtime_error("Unsupported currency");
}
}

int main()
{
std::map<std::string, currency> comodityMarketsValuesInUSD;

std::transform(
comodityMarketsValues.begin(),
comodityMarketsValues.end(),
std::inserter(comodityMarketsValuesInUSD, comodityMarketsValuesInUSD.begin()),
[](std::pair<std::string, currency> nameCurrPair) -> std::pair<std::string, currency>
{
return std::pair<std::string, currency>(
nameCurrPair.first,
currency{ std::in_place_index<USD>, toUSD(nameCurrPair.second) }
);
}
);
}

Niekto ste tu spomínal, že sa tomu nehovorí discriminated unions, ale variant. Mne na až tak nezáleží na názvosloví (v každom jazyku sa to volá trošku inak, C++ má na veľa jazykových prvkov vlastné názvy). Ide o to aby som dosiahol v praxi podobný efekt.

Ale ajtak Discriminated Union mi príde celkom výstižný názov. Lebo v OCAML sa tým tagom hovorí discriminator. A historicky discriminated unions vychádzajú z únií. Ale na githube som videl aj názvy tagged union. V každom prípade sú to algebraické dátové typy. std::variant dokáźe to isté, len má o niečo menej prehľadnú syntax (nevidím na prvý pohľad aký tag je priradený ku ktorému typu) a treba si trošku pomôcť enumeráciami ako vidím aj vo Vašich príkladoch.

Ďakujem aj Baloun echo_zulu, Wrána diskuse a ďalším za príklady, idem si ich teraz prejsť a vyskúšať a som zvedavý akým spôsobom sa líša o môjho príkladu.

Re:Discriminated unions v C++
« Odpověď #22 kdy: 26. 10. 2020, 13:29:04 »
Pro pořádek dodám i variantu s typy None a AnotherCurrency
Kód: [Vybrat]
#include <variant>
#include <string>
#include <stdexcept>
#include <cassert>
#include <iostream>

enum class CurrencyTag {
    Eur,
    Usd,
    Btc   
};

template<CurrencyTag Tag>
struct CurrencyType {
    double value = 0;
};

struct None {};

struct AnotherCurrency {
    std::string name;
    double value = 0;
};

template<CurrencyTag... Tags>
using CurrencyVariant = std::variant<None, AnotherCurrency, CurrencyType<Tags>...>;

using Currency = CurrencyVariant<CurrencyTag::Eur, CurrencyTag::Usd, CurrencyTag::Btc>;

constexpr double EUR_TO_USD = 1.1;
constexpr double BTC_TO_USD = 12000.;

struct ToUsd {
    constexpr double operator()(CurrencyType<CurrencyTag::Eur> currency) const {
        return currency.value * EUR_TO_USD;
    }
    constexpr double operator()(CurrencyType<CurrencyTag::Usd> currency) const {
        return currency.value;
    }
    constexpr double operator()(CurrencyType<CurrencyTag::Btc> currency) const {
        return currency.value * BTC_TO_USD;
    }
    template<typename T>
    constexpr double operator()(T&& t) const {
        throw std::runtime_error("Unsupported currency");
    }
};

constexpr double toUsd(const Currency &currency) {
    return std::visit(ToUsd{}, currency);
}

int main() {
    assert(toUsd(CurrencyType<CurrencyTag::Btc>{1.}) == BTC_TO_USD);
    try {
        toUsd(None{});
    } catch (const std::exception& ex) {
        std::cerr << ex.what() << std::endl;
    }
    return 0;
}

Re:Discriminated unions v C++
« Odpověď #23 kdy: 26. 10. 2020, 15:32:05 »
eště sme tady neměli oběkt + template specialization hele :o :o
Kód: [Vybrat]
#include <iostream>

enum class CurrencyTag {DOLARY, TOLARY, RUBLY};
constexpr double TOLARY_TO_DOLARY = 10.0;
constexpr double RUBLY_TO_DOLARY = 0.5;

template <CurrencyTag Tag>
class Platidlo
{
public:
    Platidlo(double val):myVal(val){}
    const double valToUsd() const;
private:
    double myVal;
   
};

template <> const double Platidlo<CurrencyTag::DOLARY> :: valToUsd () const
{
    return myVal;
}
template <> const double Platidlo<CurrencyTag::TOLARY> :: valToUsd () const
{
    return myVal * TOLARY_TO_DOLARY;
}
template <> const double Platidlo<CurrencyTag::RUBLY> :: valToUsd () const
{
    return myVal * RUBLY_TO_DOLARY;
}
 
int main()
{
    Platidlo <CurrencyTag::TOLARY> hrnecPlnejTolaru(1.0);
    std::cout << hrnecPlnejTolaru.valToUsd() << std::endl;
    return 0;
}

.................
mě jako zas tak moc neděkuj sama se tamto c++ teďko teprve učim nóó tak aby to jakoby nedopadlo jako ve vobrázku vod brůgla hele  ;D ;D ;) ;)
lidi postižený environmentálním žalem hele choděj za ekopsycholožkama hele 🤡 💆 🤡 💆

Re:Discriminated unions v C++
« Odpověď #24 kdy: 26. 10. 2020, 18:32:23 »
Pro pořádek dodám i variantu s typy None a AnotherCurrency

Super, díky moc. Pro mě je zajímavé zajímavé srovnat si tohle řešení s řešením od Fortrana, který použil čistý std::variant bez wrapování double do tagovaných typů (tedy jeho řešení bylo nejblíž původnímu zadání, tvoje je zas asi idiomatičtější v C++, a o něco bezpečnější).

Re:Discriminated unions v C++
« Odpověď #25 kdy: 26. 10. 2020, 23:46:34 »
Rozdělovat pochvaly jsi začal ty, proto ta jízlivost ode mě (skutečně asi trochu přehnaná).

...

Bohužel, v C++ praxi se zdá, že takový std::variant je natolik nepraktický na používání, že je lepší ty typy nějak odlišit (tagování, wrapnutí).


Neviem, či som udeľoval pochvaly, do tejto diskusie som sa zapojil až po odpovedi #5, ktorá začína zamyslením nad nevyslovenou otázkou prečo v tomto ľudia tápajú a prečo je v tých odpovediach zmätok. Z odborného hľadiska. Pridal som stručne napísaný postreh, ktorý si myslím, že vôbec nie je nerelevantný a to nie len v tejto diskusii. No a nad rámec toho som uviedol, čo sú dobré odpovede plus to, že v #5 je pekný kód.

A s pochvalou pre teba je to trochu naopak. Všimol som si hneď na začiatku ten tvoj súcitný povzdych nad programátormi v C++, a aj keď ma taká starostlivosť naozaj dojala, tak si myslím, že to nie je vôbec na mieste. Zvlášť ak sa orientuješ, ako si písal v tej istej vete, podľa odpovedí na otázky v "nejakom" anonymnom fóre a nie podľa aktuálnej odbornej literatúry alebo prednášok z CppCon. Chápem a dúfam, že to bol viac menej nevinný vtip, ale aj tak...

Navyše za posledné asi 4 roky sa podľa nejakej štatistiky, čo som narýchlo našiel, počet programátorov v C++ zmenil z 4,4 mil na 5,4 mil, čo je prírastok asi 23%. To si naozaj myslíš, že na svete pribudlo za niekoľko málo rokov milión masochistov? A som skoro presvedčený, že s C++20 to bude ešte rásť, dokonca pravdepodobne rapídnejšie, pretože objemovo, z hľadiska nových vecí, je v C++20 tuším väčší prírastok ako bolo v C++11 a už to bolo veľkou vecou.

Normálne by som sa voči takej neprístojnosti ohradil, takéto poznámky iba vnášajú do komunity chaos a nerešpekt k práci a rozhodnutiam iných ľudí, veď to vidíš v niektorých ďalších odpovediach. Pritom námietky pochádzajú väčšinou z neznalosti aktuálneho stavu alebo z málo informovaných a vzdelaných komunitných zdrojov.

Že si prejavil aj snahu odpovedať k veci som si všimol, tak som si povedal, že ten mínus je vyvážený plusom.

Ale tým plusom sa znamienka navzájom iba vyrušili, ostala neutralita, tak mi nenapadlo, že by som ťa mal nejako osobitne chváliť alebo vyjadriť, že teba sa moja poznámka netýka. To by som musel písať oveľa dlhšiu odpoveď a to je strašne veľa práce. Videl si predsa vyššie ako by vyzerala moja štandardná odpoveď na túto otázku, nie? Pár slov.

Čo sa tvojej odpovede týka, tak z môjho pohľadu, hoci je to informácia vedúca k odpovedi nejakému riešeniu, je to stále iba časť a to riešenie, ku ktorému to vedie nie je idiomatické pre C++ a ani pre ten spôsob programovania, ktorý má pôvodca otázky v zadaní ako zdôvovnenie prečo to vlastne potrebuje.

On má totiž jeden problém a to je ten, že z dvoch základných aspektov jeho otázky, ktorými sú "čo chcem dosiahnuť" a "akými prostriedkami to chcem dosiahnuť", u ktorých sa ukázalo, že sa nedajú oba realizovať súčasne, kladie dôraz na to menej dôležité, teda na tie prostriedky, resp. jeden z nich, ten najmenej dôležitý.

Záleží samozrejme aj na tom ako si kto interpretuje to "čo chcem dosiahnuť". Keď sa pozriem na jeho prvotný kód, tak tam vidím sumárny typ, ktorý on považuje za primárny, ale som si vedomý aj toho, že je tam aj mechanizmus spracovania, kde je použitý funkcionálny prístup k programovaniu, náhrada cyklu štandardným algoritmom a potom ešte náhrada riadiacich štruktúr ako if a switch rozoznávaním vzorov pri vyhodnocovaní položky v kontajneri jednotlivých mien.

No a pre mňa je z tohto podstatný ten mechanizmus spracovania a sumárny typ ako taký je iba jeden z prostriedkov ako ho dosianuť.

V tom jeho príklade hneď hore nikde nie je explicitné vyťahovanie hodnôt z toho sumárneho typu podľa tagov, ktoré pôsobia ako diskriminátory. Tie sa používajú na pozadí automaticky počas spracovania rozoznávaním vzorov zabudovaným v jazyku, ktorý je použitý. Sú uvedené v definícii tej funkcie, jazyk si to správne ošetrí a programátor nemusí podľa diskriminátora hľadať hodnotu a niečo s ňou robiť.

Áno, samozrejme, v C++ sa to dá naprogramovať s opakovaním jedného typu niekoľkokrát a použitím indexu vo variante v kombinácii s príkazom switch, tak ako to PO urobil vo svojom poslednom príspevku, teda predtým ako si podrobnejšie prečítal tieto odpovede. Tým ale do značnej miery opustil štýl kódu, ktorý uviedol ako príklad a vrátil sa späť k štrukturálnemu prístupu, pričom jeho momentálne riešenie nie je ani kompaktnejšie, ani prehľadnejšie ani bezpečnejšie. Myslené v kontexte reálnej aplikácie, ktorá má nejaký rozsah, niečo naozaj robí, s ohľadom na modifikácie v budúcnosti a nie iba v kontexte triviality, ktorú vmestíš na dve obrazovky.

Takýto odklon od jedného prístupu k druhému mi nedáva vôbec zmysel a ten odklon nastal iba preto, lebo PO tvrdošijne vyžaduje, aby tagovaný typ bol ten sumárny a nie typy, ktoré sú v ňom vložené, pričom ale návod ako sa to idiomaticky robí v C++ dostal už v odpovedi #1.

Navyše, nikde nie je napísané, že diskriminátor musí byť explicitný. Môže byť implicitný, vo forme samotného zložkového typu. Mechanizmus vyhodnotenia rozoznávaním vzorov, aj jeho náhrada, si to aj tak bezproblémovo priradí.

Bez toho, aby som niečo o OCaml vedel, nebol by som vôbec prekvapený, keby OCaml vnútorne ten zápis jednotlivých zložiek sumárneho typu previedol na samostatné zložkové typy a tie vnútorne použil ako diskriminátory namiesto tagov, a teda pri volaní funkcie by vzor nevyhodnocoval podľa tagu, ale podľa toho interného zložkového typu.

Takže podľa mňa existuje určitá pravdepodobnosť, že to, čo je v C++ ako tag v zložkovom type uloženom v sumárnom type a to, čo je v OCaml ako tag v sumárnom type pri zložkovom type, sú iba dva rôzne zápisy toho istého, pričom uznávam, že ten zápis v OCaml je kompaktnejší a že esteticky vyzerá lepšie.

Ale to je jedno, to je implementačný detail jazyka, podstatné je, že v oboch prípadoch funguje požadovaný mechanizmus, že zápis aj funkčnosť sú principiálne podobné a aj keď to, čo je v C++ sa oficiálne neoznačuje ako rozoznávanie vzorov, (keďže nie je zabudované priamo v jazyku v rozsahu ako je bežné v iných jazykoch a keďže nejaké návrhy na to pravé zabudované riešenie sú vo vyhodnocovaní v rámci pracovných skupín pri ISO), stále to ako rozoznávanie vzorov funguje, rozhodne aspoň ako jeho značná podmnožina.

Táto forma rozoznávania vzorov bola v C++ vždy a je realizovaná bežným preťažením funkcií.

Toľko z môjho pohľadu. Tvoj môže byť iný a možno nám aj vysvetlíš ako sa sumárny typ s opakovaným typom používa v Rust-e a aké je to praktické.

Re:Discriminated unions v C++
« Odpověď #26 kdy: 26. 10. 2020, 23:50:08 »
<flame/>Cela diskuze mi pripomina snahu pouzivat co nejobskurnejsi a nejmene zname vlastnosti z daneho jazyka. A chudaci programatori, kteri potom maji takovy kod prebrat a nedejboze upravovat.

...ale iba tí, ktorí sa vo svojom obore vytrvalo nevzdelávajú a nepíšu programy podľa dobre známych aktuálnych doporučení.

Ktorý z týchto konceptov ti pripadá byť obskurný?

(v náhodnom poradí, niektoré sú podmnožinou iných alebo sú s nimi súčasťou nejakého mechanizmu)

funkcionálne programovanie
statická alokácia pamäte
náhrada dynamickej väzby statickou
náhrada ručne písaných cyklov algoritmami zo štandardnej knižnice
vyhodnocovanie rozoznávaním vzorov
umožnenie ukladania heterogénnych dát do kontajnera
ochrana pred nechceným priradením metrov do litrov. Alebo dolárov do jenov číslo na číslo bez konverzie.
ochrana pred zabudnutím pridania položky do riadacich štuktúr
polymorfizmus bez dedičnosti


na ich implementáciu sa používajú nejaké konštrukcie jazyka, ale tie vôbec nie sú ani tajné, ani nové, ani obskurné, podľa mňa sú známe určite aspoň 10 rokov, niektoré aspoň 20, v nových verziách C++ sa píšu jednoduchšie ako v starších a aj na pohľad vyzerajú lepšie.

Re:Discriminated unions v C++
« Odpověď #27 kdy: 26. 10. 2020, 23:54:00 »
<flame/>Cela diskuze mi pripomina snahu pouzivat co nejobskurnejsi a nejmene zname vlastnosti z daneho jazyka. A chudaci programatori, kteri potom maji takovy kod prebrat a nedejboze upravovat.
si zato mužou sami že chtěli programovat v c++  ;D ;D ;) ;)

tamto hodně nový c++ trošičku vypadá jako když pejsek s kočičkou pekli dort. lidi co vyvýjej c++ si asi jako myslej že když tam nastrkaj všechny nejrůznější vychytávky s jinejch jazyků co kde jako viděli takže jakoby udělaj jazyk pro masy nóó ale myslim si že to dopadne uplně vobráceně a lidi se jim nato vykašlou. jedinej důvod proč se tendleten jazyk učim je už zmiňovanej unrealengine jinak nic. a i v tom unrealenginu de mastit různý ty blueprinty a naklikávat si všecko v gui takže to pro c++ nevidim moc dobře :o :o ??? :)

Vieš ako dlho sa ešte musíš učiť, aby si mal(a) dostatočný rozhľad a  vedel(a) to správne posúdiť?

(pauza)

Dlho. :)

...

Pejsek a kočička sú dobre platení odborníci z technologických lídrov oboru a pracujú v rámci aktivít jednej takej organizácie, ktorá má skratku ISO.

To strkanie najrôznejších vychytávok z rôznych jazykov je úplne bežná modernizácia, navyše často nie je z iných jazykov, ale z matematiky.

A každý, kto sa v tom angažuje si je veľmi dobre vedomý toho, že C++ nikdy nebude jazyk pre masy, ale pre tých, ktorí majú relevantný dôvod používať ho.

Čo sa tvojej predpovede týka, tak som niekde našiel, že za posledné asi 4 roky ubudlo zhruba mínus milión programátorov v C++. Bolo ich údajne 4.4 mil a je ich asi 5.4 mil. Predpokladám, že po vydaní C++20 ich ubudne v krátkom čase ďalších mínus niekoľkostotisíc ;)