Alternative Possibility - Implicit with

H. S. Teoh hsteoh at qfbox.info
Sat Nov 19 18:26:12 UTC 2022


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.



More information about the Digitalmars-d mailing list