<html><head><meta http-equiv="Content-Type" content="text/html; charset=us-ascii"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; line-break: after-white-space;" class="">I too have had similar thoughts, but in the end I settle for what already exists.<div class=""><br class=""></div><div class="">For any DU type I have a 'default' constructor function e.g. this one from my literate programming tool :-</div><div class=""><br class=""></div><div class=""><div class=""><font face="Menlo" class="">:- func pstate_init(string::in) = (pstate::out) is det.</font></div><div class=""><font face="Menlo" class=""><br class=""></font></div><div class=""><font face="Menlo" class="">pstate_init(Filename) = pstate(</font></div><div class=""><font face="Menlo" class=""> Filename, % For errors</font></div><div class=""><font face="Menlo" class=""> skip_text, % Initial parse state</font></div><div class=""><font face="Menlo" class=""> 0, % Pandoc size open/close filter</font></div><div class=""><font face="Menlo" class=""> plain_text(-1, ""), % Last fence header seen</font></div><div class=""><font face="Menlo" class=""> no, % Current block name scanned</font></div><div class=""><font face="Menlo" class=""> no, % Last block name scanned</font></div><div class=""><font face="Menlo" class=""> map.init : codeblock_map, % Named blocks collection</font></div><div class=""><font face="Menlo" class=""> [], % current block content</font></div><div class=""><font face="Menlo" class=""> [] % Error messages</font></div><div class=""><font face="Menlo" class="">).</font></div><div class=""><br class=""></div><div class="">If I find myself updating two or three fields one after the other more than once then I just abstract it away into a predicate so it's following DRY, and if one is really concerned with performance then you can 'inline' it by I don't go that far.</div><div class=""><br class=""></div><div class="">TBH I quite like the way Mercury --insists-- that I do things by the book, there is a stark unyielding beauty to the way it makes you write your code in certain ways, and coupled with the fact I never go over column 79, it reminds my of the good old days of a VT220!</div><div class=""><br class=""></div><div class=""><br class=""></div><div class=""><br class=""></div><div><br class=""><blockquote type="cite" class=""><div class="">On 18 Jul 2022, at 17:50, Volker Wysk <<a href="mailto:post@volker-wysk.de" class="">post@volker-wysk.de</a>> wrote:</div><br class="Apple-interchange-newline"><div class=""><div class="">Hi!<br class=""><br class="">There are two things which occur to me every now and then, about working<br class="">with discriminated union types with field names.<br class=""><br class="">1. How to initialise a value of a discriminated union type, by using field<br class="">names (similar to the way they can be used for field access and field update<br class="">functions)?<br class=""><br class="">I find myself defining a "null" value, which is initialised without usage of<br class="">field names. But this is error prone. Afters, I change fields of that null<br class="">value to get my value.<br class=""><br class="">This leads to point no. 2:<br class=""><br class="">2. How to concisely update multiple fields? You can do this in multiple<br class="">steps, like this:<br class=""><br class="">konstr1(LP3) :-<br class=""> LP1 = 'lp_link_target :='(null_link_parts, "Target"),<br class=""> LP2 = 'lp_link_subsection :='(LP1, yes("Subs.")),<br class=""> LP3 = 'lp_link_text :='(LP2, "bla").<br class=""><br class="">But this too, is rather verbose and maybe error prone.<br class=""><br class="">The code smells very much like state variables. It could be done like this:<br class=""><br class="">konstr3(Out) :-<br class=""> some [!LP] (<br class=""> !:LP = null_link_parts,<br class=""> lp_link_target("Target", !LP),<br class=""> lp_link_subsection(yes("Subs."), !LP),<br class=""> lp_link_text("bla", !LP),<br class=""> Out = !.LP<br class=""> ).<br class=""><br class="">For this, there need to be defined field update predicates:<br class=""><br class="">lp_link_target(Val, In, Out) :- Out = 'lp_link_target :='(In, Val).<br class="">lp_link_subsection(Val, In, Out) :- Out = 'lp_link_subsection :='(In, Val).<br class="">lp_link_text(Val, In, Out) :- Out = 'lp_link_text :='(In, Val).<br class=""><br class=""><br class="">So there are two things that I'm missing. <br class=""><br class="">1. A concise syntax for initialising values of a discriminated union type.<br class="">Something like this (link_parts is a data constructor):<br class=""><br class="">link_parts(lp_link_target = "Target",<br class=""> lp_link_subsection = yes("Subs."), <br class=""> lp_link_text = "bla").<br class=""><br class="">The compiler would complain when some fields aren't initialised.<br class=""><br class="">2. Some concise way to update multiple fields, like above. Maybe the<br class="">compiler could additionally generate field update predicates for the fields<br class="">(like above), similar to field update functions.<br class=""><br class=""><br class="">Cheers,<br class="">Volker<br class="">_______________________________________________<br class="">users mailing list<br class=""><a href="mailto:users@lists.mercurylang.org" class="">users@lists.mercurylang.org</a><br class="">https://lists.mercurylang.org/listinfo/users<br class=""></div></div></blockquote></div><br class=""></div></body></html>