[m-users.] Concise syntax for initialising and updating discriminated union types
Volker Wysk
post at volker-wysk.de
Tue Jul 19 04:35:26 AEST 2022
Am Dienstag, dem 19.07.2022 um 03:37 +1000 schrieb Zoltan Somogyi:
> 2022-07-19 02:50 GMT+10:00 "Volker Wysk" <post at volker-wysk.de>:
>
> > 2. How to concisely update multiple fields? You can do this in multiple
> > steps, like this:
> >
> > konstr1(LP3) :-
> > LP1 = 'lp_link_target :='(null_link_parts, "Target"),
> > LP2 = 'lp_link_subsection :='(LP1, yes("Subs.")),
> > LP3 = 'lp_link_text :='(LP2, "bla").
> >
> > But this too, is rather verbose and maybe error prone.
>
> You can also do this with
>
> LP = (((null_link_parts ^ lp_link_target := ...)
> ^ lp_link_subsection := ...)
> ^ lp_link_text := ...)
>
> though matching all the parentheses can be a bit of a pain.
I see. I guess I'll do it like this, from now on.
> > The code smells very much like state variables. It could be done like this:
> >
> > konstr3(Out) :-
> > some [!LP] (
> > !:LP = null_link_parts,
> > lp_link_target("Target", !LP),
> > lp_link_subsection(yes("Subs."), !LP),
> > lp_link_text("bla", !LP),
> > Out = !.LP
> > ).
>
> And lots of Mercury code does just such sequences of field updates,
> though none of the Mercury code I have seen started with a deliberately
> junk structure.
I'm not happy with it either. I'd prefer to do everything with field names
of some kind.
> Amongst other things, this code will do the wrong thing
> if someone ever adds a fourth field to the structure returned by null_link_parts.
Often, it will do the right thing. But I agree it isn't good style to rely
on luck. :-)
This problem is the reason why I speculated about some initialization
syntax, which would catch such cases, like a newly added field, which
doesn't get initialized properly.
> > 1. A concise syntax for initialising values of a discriminated union type.
> > Something like this (link_parts is a data constructor):
> >
> > link_parts(lp_link_target = "Target",
> > lp_link_subsection = yes("Subs."),
> > lp_link_text = "bla").
> >
> > The compiler would complain when some fields aren't initialised.
>
> This would be quite a lot of work to implement in the compiler,
> and there is already a simple way to get the effect that I presume your are
> after: a guarantee that two fields of the same type cannot be mixed up
> without that mixup being detected.
Yes, that's what I'm after.
> That way is to use semantic wrappers
> to make fields that are semantically different be actually of different types.
>
> In this example, this would mean defining
>
> :- type link_target
> ---> link_target(string).
>
> :- type link_text
> ----> link_text(string).
>
> With these, link_params(link_target("Target"), yes("Subs"), link_text("bla"))
> would work, but any permutation of the arguments would get an error.
Good point. I'm already using semantic wrappers here and there, but not
exhaustively yet.
> > 2. Some concise way to update multiple fields, like above. Maybe the
> > compiler could additionally generate field update predicates for the fields
> > (like above), similar to field update functions.
>
> This would be easier to implement, but one would want to design
> any such new feature carefully. For example,
>
> - how do you specify which subset of the fields you want setter predicates for
> (in many situations, some fields should be read-only).
Couldn't this be done the same way as it's done for setter functions?
> - it is probably the usual case that you want getter predicates for all the fields, but
>
> - sometimes you don't, and
> - even if you do, you may want to export only a subset of them, leaving the others
> private.
Dito.
> This last consideration also applies to setters, of course.
>
> You would also want some mechanism to control the names of the generated
> predicates, though a naming scheme consisting of {get,set}_<fieldname>
> would be a good default.
You could just use the field name as the predicate name in both cases, since
they differ in the arity.
> All of this info is specific to a particular type definition, so you wouldn't want
> to specify it using a compiler option; the appropriate mechanism would seem to be
> a new kind of pragma.
Bye!
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 833 bytes
Desc: This is a digitally signed message part
URL: <http://lists.mercurylang.org/archives/users/attachments/20220718/fd69568c/attachment.sig>
More information about the users
mailing list