On Saturday, 19 November 2022 at 08:49:31 UTC, Walter Bright wrote:
> The contextual inference only takes place in certain contexts.
I like this. This is much better than introducing a whole new set of
lookup rules with all sorts of complicated unexpected interactions with
existing lookup behaviour.
> Perhaps we can run with that idea. Let's take case statements:
[...]
> and recognize that the SwitchExpression is of type WordLetterOfTheDay.
Exactly!!! The type of SwitchExpression already tells you what type the
case labels must be. So there is no need to have to repeat the enum type
name over and over again, for every case label. Just have the compiler
implicitly convert:
switch (x) { ... }
to:
switch (x) with(typeof(x)) { ... }
when x is an enum value, and that solves this particular case.
> Implicitly enclose the switch body with a `with (WordLetterOfTheDay)`
> resulting in:
>
> enum WordLetterOfTheDay{ a,b,c,d/*...*/ }
>
> void main(){
> auto letterToday = WordLetterOfTheDay.b;
>
> import std.stdio;
> switch(letterToday){
> case a:
> writeln("Apple");
> break;
> case b:
> writeln("Bicycle");
> break;
> case c:
> writeln("Caterpillar");
> break;
> case d:
> writeln("Didgeridoo");
> break;
> /*...*/
> }
> }
>
> Note the disappearance of the `$`, and use of the leading `.` operator
> retains its existing meaning.
Yes, this is a much better solution.
> Applying the same to Initializers and assignments:
>
> enum A{ a,b,c,d }
>
> struct S{ A one, two; }
>
> void main(){
> A myA1 = b; // myA1 = A.b
> A myA2 = b | c; // myA2 = A.c
> auto myA3 = b; // error, b is undefined
+1, this makes sense.
[...]
> To Return statements:
>
> enum A{ a,b,c,d }
>
> A myFn(){
> return c; //returns A.c
> }
>
> auto myBrokenFn(){
> return c; // error, c is undefined
> }
Also makes sense.
> Argument lists:
>
> Only works if there are no overloads.
There's another use case to address: default parameter declarations.
Current syntax:
enum LongEnumName { abc, def, ghi }
int myFunc(LongEnumName x = LongEnumName.abc) { ... }
Desired syntax:
enum LongEnumName { abc, def, ghi }
int myFunc(LongEnumName x = abc) { ... }
i.e., the RHS of a default parameter should be treated just like the
initialization of an enum variable, there should be an implicit `with`.
Also common in my code:
enum LongEnumName { abc, def, ghi }
int myFunc(LongEnumName x = LongEnumName.init) { ... }
Desired syntax:
enum LongEnumName { abc, def, ghi }
int myFunc(LongEnumName x = init) { ... }
> Array literals:
>
> enum A{ a,b,c,d }
>
> // (A)
> A[4] x = [a, b, c, d];
Nice.
[...]
> Now, suppose instead you write:
>
> enum A{ a,b,c,d }
>
> A b = c;
> A[4] x = [a, b, c, d];
>
> Is the `b` A.b or A.c? A.b since the `with` has a narrower scope than
> the local `b`. If the user wants the local `b`, he will need to rename
> it.
Makes sense.
> Advantages of this scheme:
>
> 1. doesn't need the special `$` which people don't seem to like, and
> using `.` conflicts with existing use
>
> 2. makes use of the already present `with` semantics
>
> 3. seems to have a natural feel to it
Yes, this proposal is much better. Adding the `$` or `.` syntax just
seems to have much farther-reaching consequences and interactions with
existing features than is justifiable for something that's arguably
merely syntactic sugar. Leveraging the existing `with` construct is a
much less-intrusive, IMO superior approach.
T
--
Questions are the beginning of intelligence, but the fear of God is the beginning of wisdom.
|