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