Type Inference for Struct/Enum Literals
IchorDev
zxinsworld at gmail.com
Tue Jul 9 03:39:29 UTC 2024
On Monday, 8 July 2024 at 18:17:16 UTC, Quirin Schroll wrote:
> For that, we could add this to the language:
> ```d
> with MySelfExplanatoryType flag = A | B | C;
> ```
Unfortunately this only helps with bit-flag style enums. Using
`with` for those is already some kind of solution (same as for
large `switch` statements). This is why my examples focus on the
(in my experience) everyday case of using many different enum
types, usually passed to function calls, but only ever using a
couple of literals per enum type, and having these scattered
throughout your code without a good spot to use a `with` block to
shorten **any** of them. `with` is a great feature, but it only
solves the problem of mass repetition for **one type** in **one
place** at a time. Yes, you can stack `with`, but when you're
using 5 different types, once each, using `with` is like applying
a bandaid to help with internal bleeding.
> I get that `setState(invalid)` is nicer to the programmer than
> `setState(enum.invalid)`, but the advantage is that there’s
> zero ambiguity of intent.
Having no prefix like that is definitely not my preference at
all. Primarily I'd like `setState(.invalid)`, but I'm open to
other prefixes. If we're going for an explicit syntax that
doesn't break anything existing then I vote for `\`, or `:`, or
maybe `#` if we can reclaim it from the clutches of dmd's
grammar. We also haven't examined `?`, but that option relies on
Walter's sumtype `?` prefix not going into the language (I'm not
sure where that's at right now).
> There could even be a new parameter storage class named `with`
> that would allow dropping `enum.` for constants of a particular
> `enum` type:
> ```d
> class Widget
> {
> void setState(with State newState) { … }
>
> void set(StateTag _ = StateTag(), with State newState) { … }
> void set(ShapeTag _ = ShapeTag(), with Shape newShape) { … }
> }
>
> void main()
> {
> Widget w = new Widget;
> w.setState(State.invalid); // okay
> w.setState(enum.invalid); // new: okay, general enum type
> inference
> w.setState(invalid); // new: okay, special `with` parameter
>
> w.set(newState: invalid); // new: okay, special `with`
> parameter
> w.set(newShape: square); // new: okay, special `with`
> parameter
> }
> ```
> A `with` parameter is allowed for `enum` type parameters, and
> advised when
> 1. * either the name of the function makes absolutely clear
> what is passed,
> * or there is a mechanism in place that requires use of
> named arguments and the arguments’ name makes things clear, and
> 2. there is probable cause that the function is called with
> members of the `enum` type.
This just a bit too much. Less is more when it comes to type
inference, and a simple shortcut should become a whole system
where the caller has to keep track of whether the callee allows
them to use a shortcut or not, while *still* having the ambiguity
of not writing any kind of 'inferred type' prefix.
With a short prefix there can no ambiguity as to whether type
inference is being used or not, while still keeping code succinct.
More information about the dip.ideas
mailing list