www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Discussion Thread: DIP 1044--Enum Type Inference--Community Review

reply Mike Parker <aldacron gmail.com> writes:


This is the discussion thread for the first round of Community 
Review of DIP 1044, "Enum Type Inference":

https://github.com/dlang/DIPs/blob/e2ca557ab9d3e60305a37da0d5b58299e0a9de0e/DIPs/DIP1044.md

The review period will **end at 11:59 PM ET on December 3**, or 
when I make a post declaring it complete. Discussion in this 
thread may continue beyond that point.

Here in the discussion thread, you are free to discuss anything 
and everything related to the DIP. Express your support or 
opposition, debate alternatives, argue the merits, etc.

However, if you have any specific feedback on how to improve the 
proposal itself, then please post it in the Feedback Thread. The 
Feedback Thread will be the source for the review summary that I 
will write at the end of this review round. I will post a link to 
that thread immediately following this post. Just be sure to read 
and understand the Reviewer Guidelines before posting there:

https://github.com/dlang/DIPs/blob/master/docs/guidelines-reviewers.md

And my blog post on the difference between the Discussion and 
Feedback threads:

https://dlang.org/blog/2020/01/26/dip-reviews-discussion-vs-feedback/

Please stay on topic here. I will delete posts that are 
completely off-topic.
Nov 18 2022
next sibling parent Mike Parker <aldacron gmail.com> writes:
On Friday, 18 November 2022 at 15:37:31 UTC, Mike Parker wrote:

 However, if you have any specific feedback on how to improve 
 the proposal itself, then please post it in the Feedback 
 Thread. The Feedback Thread will be the source for the review 
 summary that I will write at the end of this review round. I 
 will post a link to that thread immediately following this post.
The Feedback Thread is here: https://forum.dlang.org/post/yhlkkahzhabrhtyyqtpd forum.dlang.org
Nov 18 2022
prev sibling next sibling parent reply monkyyy <crazymonkyyy gmail.com> writes:
 using $
If I define opDollar to return an enum; and you define an opIndex to take enums; does it all work?
Nov 18 2022
parent reply IGotD- <nise nise.com> writes:
On Friday, 18 November 2022 at 17:54:42 UTC, monkyyy wrote:
 using $
If I define opDollar to return an enum; and you define an opIndex to take enums; does it all work?
The $myEnum syntax is really hideous compared to the .myEnum. The .myEnum syntax feels natural where $myEnum looks like it is some kind macro parameter or something. There is a reason that all other example languages like Swift use the . syntax. Is it possible to use the . syntax but there is a search hierarchy? If there is a global with the same enum name, you must give the full enum name. There might creep in serious bugs, however often you will have some kind of type mismatch. The $ syntax is so ugly that I don't want this DIP in its current form.
Nov 18 2022
next sibling parent reply H. S. Teoh <hsteoh qfbox.info> writes:
On Fri, Nov 18, 2022 at 07:14:14PM +0000, IGotD- via 
Digitalmars-d wrote:
 On Friday, 18 November 2022 at 17:54:42 UTC, monkyyy wrote:
 using $
If I define opDollar to return an enum; and you define an opIndex to take enums; does it all work?
The $myEnum syntax is really hideous compared to the .myEnum. The .myEnum syntax feels natural where $myEnum looks like it is some kind macro parameter or something. There is a reason that all other example languages like Swift use the . syntax.
Yeah, `$` is really hideous and sticks out like a sore thumb in typical D code. On top of that, it overloads the current usage of $ to something completely unrelated, which makes it look really messy. Why can't we just stick with `.`?
 Is it possible to use the . syntax but there is a search 
 hierarchy? If
 there is a global with the same enum name, you must give the 
 full enum
 name. There might creep in serious bugs, however often you will 
 have
 some kind of type mismatch.
[...] Here's my proposal: use `.` instead of `$`, and if .identifier is ambiguous in any way at all, prohibit ITE and require spelling out the enum in full. I.e., prohibit it if there's any ambiguity at all with a module name, any global identifier, or it can be a member of multiple enums currently in scope. After all, your typical use case is an enum member with unique member names, such that it's a pain to have to spell out the enum type since it's already obvious from the name which enum it must belong to. If the enum members don't have obviously unique names (i.e., it's ambiguous with some top-level identifier), then it should be spelled out in full, we should just prohibit eliding the type name. T -- Don't drink and derive. Alcohol and algebra don't mix.
Nov 18 2022
next sibling parent Timon Gehr <timon.gehr gmx.ch> writes:
On 18.11.22 20:33, H. S. Teoh wrote:
 
 Here's my proposal: use `.` instead of `$`, and if .identifier is
 ambiguous in any way at all, prohibit ITE and require spelling out the
 enum in full. I.e., prohibit it if there's any ambiguity at all with a
 module name, any global identifier, or it can be a member of multiple
 enums currently in scope.
Well, what if you _wanted_ to access the module-scope variable? I guess there are workarounds, but this still seems a bit messy. Probably still better than using $identifier though.
Nov 18 2022
prev sibling next sibling parent reply Dukc <ajieskola gmail.com> writes:
On Friday, 18 November 2022 at 19:33:05 UTC, H. S. Teoh wrote:
 On Fri, Nov 18, 2022 at 07:14:14PM +0000, IGotD- via 
 Digitalmars-d wrote:
 The $myEnum syntax is really hideous compared to the .myEnum. 
 The
 .myEnum syntax feels natural where $myEnum looks like it is 
 some kind
 macro parameter or something. There is a reason that all other 
 example
 languages like Swift use the . syntax.
Yeah, `$` is really hideous and sticks out like a sore thumb in typical D code. On top of that, it overloads the current usage of $ to something completely unrelated, which makes it look really messy. Why can't we just stick with `.`?
(He / She)? gave a good reason, that already means "fetch from module namespace". While we could devise rules to make those disambiguate from each other, it'd be too much complexity for slightly better-looking syntax IMO. I thus prefer `$`. However, Timons idea, `_`, is even better.
Nov 19 2022
parent IchorDev <zxinsworld gmail.com> writes:
On Saturday, 19 November 2022 at 08:48:54 UTC, Dukc wrote:
 (He / She)? gave a good reason, that already means "fetch from 
 module namespace". While we could devise rules to make those 
 disambiguate from each5 other, it'd be too much complexity for 
 slightly better-looking syntax IMO.

 I thus prefer `$`. However, Timons idea, `_`, is even better.
If you're referring to me (I'm the DIP Author), then it's she/her. The `_` is a bit confusing. Would it be `_.member`? If so then I personally think `$` is better because it's 1 keystroke fewer. I chose `$` because its current use can peacefully co-exist with ETI and it's only two keystrokes, meaning that it beats writing a 2+ enum type name. If it was `_member` then it'd just look like a normal symbol.
Nov 20 2022
prev sibling parent IchorDev <zxinsworld gmail.com> writes:
On Friday, 18 November 2022 at 19:33:05 UTC, H. S. Teoh wrote:
 Here's my proposal: use `.` instead of `$`, and if .identifier 
 is
 ambiguous in any way at all, prohibit ITE and require spelling 
 out the
 enum in full. I.e., prohibit it if there's any ambiguity at all 
 with a
 module name, any global identifier, or it can be a member of 
 multiple
 enums currently in scope.
This could break pre-existing code, so it's a definite no unfortunately. I don't want to break working code just to add a convenient shortcut. That's like having a highway built through your house!
Nov 20 2022
prev sibling parent ryuukk_ <ryuukk.dev gmail.com> writes:
On Friday, 18 November 2022 at 19:14:14 UTC, IGotD- wrote:
 On Friday, 18 November 2022 at 17:54:42 UTC, monkyyy wrote:
 using $
If I define opDollar to return an enum; and you define an opIndex to take enums; does it all work?
The $myEnum syntax is really hideous compared to the .myEnum. The .myEnum syntax feels natural where $myEnum looks like it is some kind macro parameter or something. There is a reason that all other example languages like Swift use the . syntax. Is it possible to use the . syntax but there is a search hierarchy? If there is a global with the same enum name, you must give the full enum name. There might creep in serious bugs, however often you will have some kind of type mismatch. The $ syntax is so ugly that I don't want this DIP in its current form.
I agree, i also much prefer the .Enum syntax, it's more natural and easier on the eyes
Nov 18 2022
prev sibling next sibling parent reply bachmeier <no spam.net> writes:
On Friday, 18 November 2022 at 15:37:31 UTC, Mike Parker wrote:


 This is the discussion thread for the first round of Community 
 Review of DIP 1044, "Enum Type Inference":
[...] I'm skeptical that adding this type of complexity to the language is worth it. Not just that this would add considerably to the learning curve, but because seemingly harmless changes to another part of your program would suddenly introduce ambiguity and cause it to no longer compile. Consider this example: ``` import std; enum JavaStyleGinormousName { a, b, c, d} void main() { auto var = JavaStyleGinormousName.a; writeln(var); alias B = JavaStyleGinormousName; auto var2 = B.a; writeln(var2); } ``` This makes everything explicit, with no surprises and no additional learning curve for the new user. This proposal essentially boils down to an implicit ``` alias $. = [something inferred by the compiler depending on the context ```
Nov 18 2022
next sibling parent reply monkyyy <crazymonkyyy gmail.com> writes:
On Friday, 18 November 2022 at 18:32:44 UTC, bachmeier wrote:
 no additional learning curve for the new user. This proposal 
 essentially boils down to an implicit

 ```
 alias $. = [something inferred by the compiler depending on the 
 context
 ```
Ds enum syntax is verbose compared to c; and the code block probaly isnt possible to write
Nov 18 2022
parent reply XavierAP <n3minis-git yahoo.es> writes:
On Friday, 18 November 2022 at 18:54:01 UTC, monkyyy wrote:
 Ds enum syntax is verbose compared to c; and the code block 
 probaly isnt possible to write
I know I'm not teaching anything that's not known, but languages was absolutely intentional. And IMHO the reasons (against the C syntax) stand.
Nov 22 2022
parent reply deadalnix <deadalnix gmail.com> writes:
On Tuesday, 22 November 2022 at 21:44:00 UTC, XavierAP wrote:
 On Friday, 18 November 2022 at 18:54:01 UTC, monkyyy wrote:
 Ds enum syntax is verbose compared to c; and the code block 
 probaly isnt possible to write
I know I'm not teaching anything that's not known, but qualified, was absolutely intentional. And IMHO the reasons (against the C syntax) stand.
And wait, there is more: we have anonymous enums: ```d enum { A, B } ``` For these who are allergic to named enums.
Nov 23 2022
next sibling parent reply ryuukk_ <ryuukk.dev gmail.com> writes:
On Wednesday, 23 November 2022 at 11:57:48 UTC, deadalnix wrote:
 On Tuesday, 22 November 2022 at 21:44:00 UTC, XavierAP wrote:
 On Friday, 18 November 2022 at 18:54:01 UTC, monkyyy wrote:
 Ds enum syntax is verbose compared to c; and the code block 
 probaly isnt possible to write
I know I'm not teaching anything that's not known, but qualified, was absolutely intentional. And IMHO the reasons (against the C syntax) stand.
And wait, there is more: we have anonymous enums: ```d enum { A, B } ``` For these who are allergic to named enums.
```D // verbose API, readable struct SuperLongStruct { struct SuperLongInnerStruct { enum SuperLongEnum { VALUE_A, VALUE_B } SuperLongEnum super_long_flags; } SuperLongInnerStruct some_data; } // oh shoot SuperLongStruct super_long_struct = { some_data: { super_long_flags: SuperLongStruct.SuperLongInnerStruct.SuperLongEnum.VALUE_A | SuperLongStruct.SuperLongInnerStruct.SuperLongEnum.VALUE_A } }; // oh nice! SuperLongStruct super_long_struct = { some_data: { super_long_flags: .VALUE_A | .VALUE_A } }; ``` no need to introduce noise, no need to care about an alias that is leaking, the usage of the API is simple and expressive, i'm not sacrificing the API with simpler and meaningless names i make fully use of scoped types in D, and i avoid the noisy verbosity that comes with it as a result Adam's idea to use `auto` could be the proper compromise It's not about what other languages do, it's about how it helps the user avoid making their code unreadable ```D MyType value = MyType.some; ``` is `.some` a static function? does it return something? is it a static variable? an enum? you don't know! so the argument that it Enum Type Inference reduce readability is not valid, if your API is not readable, that's the problem Helping users be more expressive and less verbose helps them keep and maintain proper naming for their types/variables, wich helps readability ```D AttackType attack_type = .MELEE; (..) switch (attack_type) { case .MELEE: break; } ``` now your variable name carry more and proper information about what it is,
Nov 23 2022
next sibling parent reply deadalnix <deadalnix gmail.com> writes:
On Wednesday, 23 November 2022 at 13:41:12 UTC, ryuukk_ wrote:
 ```D
 // verbose API, readable
 struct SuperLongStruct
 {
     struct SuperLongInnerStruct
     {
         enum SuperLongEnum
         {
             VALUE_A, VALUE_B
         }

         SuperLongEnum super_long_flags;
     }
     SuperLongInnerStruct some_data;
 }

 // oh shoot

 SuperLongStruct super_long_struct = {
     some_data: {
         super_long_flags:  
 SuperLongStruct.SuperLongInnerStruct.SuperLongEnum.VALUE_A | 
 SuperLongStruct.SuperLongInnerStruct.SuperLongEnum.VALUE_A
     }
 };

 // oh nice!

 SuperLongStruct super_long_struct = {
     some_data: {
         super_long_flags: .VALUE_A | .VALUE_A
     }
 };

 ```
Try `alias E = SuperLongStruct.SuperLongInnerStruct.SuperLongEnum;`
 ```D
 AttackType attack_type = .MELEE;


 (..)


 switch (attack_type)
 {
     case .MELEE:
     break;
 }



 ```

 now your variable name carry more and proper information about 
 what it is,
```d auto attack_type = AttackType.MELEE; switch (attack_type) with(AttackType) { case MELEE: break; } ```
Nov 23 2022
parent reply ryuukk_ <ryuukk.dev gmail.com> writes:
On Wednesday, 23 November 2022 at 14:21:23 UTC, deadalnix wrote:
 On Wednesday, 23 November 2022 at 13:41:12 UTC, ryuukk_ wrote:
 ```D
 // verbose API, readable
 struct SuperLongStruct
 {
     struct SuperLongInnerStruct
     {
         enum SuperLongEnum
         {
             VALUE_A, VALUE_B
         }

         SuperLongEnum super_long_flags;
     }
     SuperLongInnerStruct some_data;
 }

 // oh shoot

 SuperLongStruct super_long_struct = {
     some_data: {
         super_long_flags:  
 SuperLongStruct.SuperLongInnerStruct.SuperLongEnum.VALUE_A | 
 SuperLongStruct.SuperLongInnerStruct.SuperLongEnum.VALUE_A
     }
 };

 // oh nice!

 SuperLongStruct super_long_struct = {
     some_data: {
         super_long_flags: .VALUE_A | .VALUE_A
     }
 };

 ```
Try `alias E = SuperLongStruct.SuperLongInnerStruct.SuperLongEnum;`
 ```D
 AttackType attack_type = .MELEE;


 (..)


 switch (attack_type)
 {
     case .MELEE:
     break;
 }



 ```

 now your variable name carry more and proper information about 
 what it is,
```d auto attack_type = AttackType.MELEE; switch (attack_type) with(AttackType) { case MELEE: break; } ```
```D struct Action { AttackType attack_type; } // no auto here ``` in your switch, did you read it? switch attack_type with AttackType this is not appealing and is the noise and repetition that needs to be suppressed i was verbose when i declared my variable name, that's enough and you didn't read my other comment why should i declare an alias? it leaks the symbol to the scope, it is another symbol that i need to remember when i refactor, and it adds cognitive load when i read my whole module, too much gymnastic and scope bloat
Nov 23 2022
parent reply ryuukk_ <ryuukk.dev gmail.com> writes:
On Wednesday, 23 November 2022 at 15:21:07 UTC, ryuukk_ wrote:
 On Wednesday, 23 November 2022 at 14:21:23 UTC, deadalnix wrote:
 On Wednesday, 23 November 2022 at 13:41:12 UTC, ryuukk_ wrote:
 ```D
 // verbose API, readable
 struct SuperLongStruct
 {
     struct SuperLongInnerStruct
     {
         enum SuperLongEnum
         {
             VALUE_A, VALUE_B
         }

         SuperLongEnum super_long_flags;
     }
     SuperLongInnerStruct some_data;
 }

 // oh shoot

 SuperLongStruct super_long_struct = {
     some_data: {
         super_long_flags:  
 SuperLongStruct.SuperLongInnerStruct.SuperLongEnum.VALUE_A | 
 SuperLongStruct.SuperLongInnerStruct.SuperLongEnum.VALUE_A
     }
 };

 // oh nice!

 SuperLongStruct super_long_struct = {
     some_data: {
         super_long_flags: .VALUE_A | .VALUE_A
     }
 };

 ```
Try `alias E = SuperLongStruct.SuperLongInnerStruct.SuperLongEnum;`
 ```D
 AttackType attack_type = .MELEE;


 (..)


 switch (attack_type)
 {
     case .MELEE:
     break;
 }



 ```

 now your variable name carry more and proper information 
 about what it is,
```d auto attack_type = AttackType.MELEE; switch (attack_type) with(AttackType) { case MELEE: break; } ```
```D struct Action { AttackType attack_type; } // no auto here ``` in your switch, did you read it? switch attack_type with AttackType this is not appealing and is the noise and repetition that needs to be suppressed i was verbose when i declared my variable name, that's enough and you didn't read my other comment why should i declare an alias? it leaks the symbol to the scope, it is another symbol that i need to remember when i refactor, and it adds cognitive load when i read my whole module, too much gymnastic and scope bloat
now this example: ```D switch (action.attack_type) with(AttackType) { case MELEE: if (action.weapon_type == SuperLongType.InnerType.SWORD) (...) break; } switch (action.attack_type) with(AttackType) with(SuperLongType.InnerType) with(SuperLongType.AnotherInnerType) { case MELEE: if (action.weapon_type == SWORD) (...) if (action.buff_type == STR_UP) (...) break; } ``` Yeah no thanks.. There it's miles better, you don't need no alias to workaround anything that bloats scope and adds superfluous and unnecessary cognitive load, you read the variable name and you know what you deal with ```D switch (action.attack_type) { case MELEE: if (action.weapon_type == .SWORD) (...) if (action.buff_type == .STR_UP) (...) break; } ```
Nov 23 2022
parent reply RTM <riven baryonides.ru> writes:
On Wednesday, 23 November 2022 at 15:26:46 UTC, ryuukk_ wrote:

 ```D
 switch (action.attack_type) {
     case MELEE:
         if (action.weapon_type == .SWORD)
             (...)


         if (action.buff_type == .STR_UP)
             (...)
     break;

 }
 ```
Inconsistency. Should be with/without dot in either case.
Nov 23 2022
parent ryuukk_ <ryuukk.dev gmail.com> writes:
On Wednesday, 23 November 2022 at 16:30:56 UTC, RTM wrote:
 On Wednesday, 23 November 2022 at 15:26:46 UTC, ryuukk_ wrote:

 ```D
 switch (action.attack_type) {
     case MELEE:
         if (action.weapon_type == .SWORD)
             (...)


         if (action.buff_type == .STR_UP)
             (...)
     break;

 }
 ```
Inconsistency. Should be with/without dot in either case.
You are nitpicking, that's a forum quote issue, it was my code that he quoted and edited, all my examples have the dot
Nov 23 2022
prev sibling parent reply XavierAP <n3minis-git yahoo.es> writes:
On Wednesday, 23 November 2022 at 13:41:12 UTC, ryuukk_ wrote:
 ```D
 // verbose API, readable
 struct SuperLongStruct
 {
     struct SuperLongInnerStruct
     {
         enum SuperLongEnum
         {
             VALUE_A, VALUE_B
         }

         SuperLongEnum super_long_flags;
     }
     SuperLongInnerStruct some_data;
 }
Isn't this design artificially conceived to shoe-horn the proposed change as a solution? Such nesting would probably never be advisable, too convoluted and coupled. And in this example (though I understand it's a toy example) there is no reason for nesting: no hiding, and no access of private fields by the nested types. Certainly the enum here has in this design no reason to be nested other than _namespacing_ it into the other types; and then avoiding expressing this (seemingly absurd but purposeful) namespacing is argued as the reason for a language change. Isn't it more adequate in this example to just un-nest this declaration?
Nov 27 2022
next sibling parent reply ryuukk_ <ryuukk.dev gmail.com> writes:
On Sunday, 27 November 2022 at 21:58:00 UTC, XavierAP wrote:
 On Wednesday, 23 November 2022 at 13:41:12 UTC, ryuukk_ wrote:
 ```D
 // verbose API, readable
 struct SuperLongStruct
 {
     struct SuperLongInnerStruct
     {
         enum SuperLongEnum
         {
             VALUE_A, VALUE_B
         }

         SuperLongEnum super_long_flags;
     }
     SuperLongInnerStruct some_data;
 }
Isn't this design artificially conceived to shoe-horn the proposed change as a solution? Such nesting would probably never be advisable, too convoluted and coupled. And in this example (though I understand it's a toy example) there is no reason for nesting: no hiding, and no access of private fields by the nested types. Certainly the enum here has in this design no reason to be nested other than _namespacing_ it into the other types; and then avoiding expressing this (seemingly absurd but purposeful) namespacing is argued as the reason for a language change. Isn't it more adequate in this example to just un-nest this declaration?
Ok so you disagree just to disagree, that's unfortunate Here if you want a snippet of a code from my project: https://forum.dlang.org/post/bapjpjlbljjhhwcworvz forum.dlang.org ```D ctx.network_state = State.NetworkState.CONNECTED; // vs ctx.network_state = .CONNECTED; ``` I don't do OOP or any of that encapsulation crap If you don't see the code above as an improvement, then you can keep use the old behavior, nothing will change for you, as for me i will keep advocate for it And no, i will not subscribe to XavierAP_CODE_STYLE_GUIDELINE.md document
Nov 27 2022
next sibling parent ryuukk_ <ryuukk.dev gmail.com> writes:
On Sunday, 27 November 2022 at 23:13:39 UTC, ryuukk_ wrote:

And you cut off the most interesting part of my code example that 
you quoted, i'll psot it again for clarity:

from: 
https://forum.dlang.org/post/wrcrrmjgvrckyyvwfxec forum.dlang.org

```
// verbose API, readable
struct SuperLongStruct
{
     struct SuperLongInnerStruct
     {
         enum SuperLongEnum
         {
             VALUE_A, VALUE_B
         }

         SuperLongEnum super_long_flags;
     }
     SuperLongInnerStruct some_data;
}

// oh shoot

SuperLongStruct super_long_struct = {
     some_data: {
         super_long_flags:  
SuperLongStruct.SuperLongInnerStruct.SuperLongEnum.VALUE_A | 
SuperLongStruct.SuperLongInnerStruct.SuperLongEnum.VALUE_A
     }
};

// oh nice!

SuperLongStruct super_long_struct = {
     some_data: {
         super_long_flags: .VALUE_A | .VALUE_A
     }
};

```
Nov 27 2022
prev sibling parent reply XavierAP <n3minis-git yahoo.es> writes:
On Sunday, 27 November 2022 at 23:13:39 UTC, ryuukk_ wrote:
 Ok so you disagree just to disagree, that's unfortunate

 Here if you want a snippet of a code from my project: 
 https://forum.dlang.org/post/bapjpjlbljjhhwcworvz forum.dlang.org

 ```D
 ctx.network_state = State.NetworkState.CONNECTED;

 // vs

 ctx.network_state = .CONNECTED;
I didn't mean to be dismissive. And for the record I'd be OK with adding to D most kinds of inference as long as it didn't require new syntax (such as `$` or adding to `.`) and were 100% sure and safe. This might be possible for enums at least in initializations or even assignments (?) but it's not the current DIP (and there are probably other difficulties even with this). All I'm saying is, nesting your types has no other effect (since there's no private data in between) than namespacing them, and so requiring yourself to qualify this namespacing. This is your choice; purely stylistic as far as I can tell. Then you want to be able to write code without this namespacing, and for this you suggest a lexical change. But this particular use case could be solved with a different stylistic design choice when declaring your types; so I don't see the need for the language change. This is my main point: the DIP discussion should start on the concrete problem(s) and use cases that it's supposed to solve: * enums imported from C * nested enums * long/bad names * ...? The discussion should not be so subjective or revolve around what styles it enables or what ones different people prefer.
Nov 28 2022
parent Quirin Schroll <qs.il.paperinik gmail.com> writes:
On Monday, 28 November 2022 at 09:33:56 UTC, XavierAP wrote:
 I didn't mean to be dismissive. And for the record I'd be OK 
 with adding to D most kinds of inference as long as it didn't 
 require new syntax (such as `$` or adding to `.`) and were 100% 
 sure and safe. This might be possible for enums at least in 
 initializations or even assignments (?) but it's not the 
 current DIP (and there are probably other difficulties even 
 with this).
There isn’t much that’s 100% safe in a pragmatic context. Inference for `switch`, initialization and assignment is possible except special compound assignments like those that lower to `opIndexAssign`, where the left-hand side operand need not have a type at all. Even then, a best-effort strategy might still be useful and work in almost all cases. In many cases, an assignment `lhs = rhs` could be lowered to ```d lhs = (){ with (typeof(lhs)) return rhs; }(); ``` This might not be foolproof, but it’s probably “safe unless you do obvious stupid”.
Nov 30 2022
prev sibling parent reply Max Samukha <maxsamukha gmail.com> writes:
On Sunday, 27 November 2022 at 21:58:00 UTC, XavierAP wrote:

 (seemingly absurd but purposeful)
Why is that absurd? This: ``` struct Entity { enum Kind { } Kind entity; } ``` instead of this: ``` enum EntityKind { } struct Entity { EntityKind entity; } ``` is a common practice. If the inner definitions become too long, it does make sense to move them to the outer scope (and then optionally alias inside the inner scope).
Nov 27 2022
parent XavierAP <n3minis-git yahoo.es> writes:
On Monday, 28 November 2022 at 07:06:56 UTC, Max Samukha wrote:
 Why is that absurd?

 This:
 ```
 struct Entity
 {
     enum Kind
     {
     }

     Kind entity;
 }
 ```
 instead of this:
 ```
 enum EntityKind
 {
 }

 struct Entity
 {
     EntityKind entity;
 }
 ```
 is a common practice.
About nesting in general I've replied to ryuukk_ at https://forum.dlang.org/post/gjhvbrehodkabzvewopx forum.dlang.org In this example there's little difference, between having to type (or not) either `Entity.Kind` or `EntityKind`. It's indeed a good example how nesting without private data is a purely stylistic namespacing choice. (So imo no one forces you to use it to an extent that requires you to type too much or otherwise makes your life difficult.)
Nov 28 2022
prev sibling parent reply 12345swordy <alexanderheistermann gmail.com> writes:
On Wednesday, 23 November 2022 at 11:57:48 UTC, deadalnix wrote:
 On Tuesday, 22 November 2022 at 21:44:00 UTC, XavierAP wrote:
 On Friday, 18 November 2022 at 18:54:01 UTC, monkyyy wrote:
 Ds enum syntax is verbose compared to c; and the code block 
 probaly isnt possible to write
I know I'm not teaching anything that's not known, but qualified, was absolutely intentional. And IMHO the reasons (against the C syntax) stand.
And wait, there is more: we have anonymous enums: ```d enum { A, B } ``` For these who are allergic to named enums.
That doesn't work when interacting with existing c code base here.
Nov 23 2022
parent reply XavierAP <n3minis-git yahoo.es> writes:
On Wednesday, 23 November 2022 at 15:13:09 UTC, 12345swordy wrote:
 That doesn't work when interacting with existing c code base 
 here.
Funny thing is, because C enums being unqualified and not strongly typed was considered a problem, C got into the habit of repeating every enum's type name in every of its values e.g. enum IMG_INIT { IMG_INIT_jpg, IMG_INIT_png } P.S. of course it doesn't work for that. But interoperating with C isn't the problem here, because C enums don't map to D enums but to integers?
Nov 23 2022
parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 11/23/2022 8:13 AM, XavierAP wrote:
 But interoperating with C isn't the 
 problem here, because C enums don't map to D enums but to integers?
ImportC maps C enums to D enums.
Nov 23 2022
parent reply XavierAP <n3minis-git yahoo.es> writes:
On Wednesday, 23 November 2022 at 23:50:55 UTC, Walter Bright 
wrote:
 On 11/23/2022 8:13 AM, XavierAP wrote:
 But interoperating with C isn't the problem here, because C 
 enums don't map to D enums but to integers?
ImportC maps C enums to D enums.
Ah nice. I didn't know, I'm currently playing with (a version of?) Derelict which binds in a different, more C-like and pointy way. I'm just worried that the defect of C enums being unqualified/weakly typed caused the workaround/defect of repeating the type name in every value, which when imported into a better enum language like D causes annoyance, which causes some people to wish for enums not requiring qualification to avoid the repetition. Whereas the cause of the repetition is the specific enum declarations (which can be aliased), not the D language. When an enum is properly named without repetition I think it's good that you have to qualify it -- outside possibly the special case of initialization. So did the designers of many modern languages including the C++ committee. So I still personally think this proposal is a bad idea. 😇
Nov 24 2022
parent bauss <jacobbauss gmail.com> writes:
On Thursday, 24 November 2022 at 14:01:27 UTC, XavierAP wrote:
 Ah nice. I didn't know, I'm currently playing with (a version 
 of?) Derelict which binds in a different, more C-like and 
 pointy way.
I believe Derelict was the old way of binding to C, where as BindBC is the new and modern way. A lot of the Derelict projects are now deprecated in favor of their BindBC counterpart.
Nov 24 2022
prev sibling parent reply Nick Treleaven <nick geany.org> writes:
On Friday, 18 November 2022 at 18:32:44 UTC, bachmeier wrote:
 ```
 import std;

 enum JavaStyleGinormousName { a, b, c, d}

 void main() {
     auto var = JavaStyleGinormousName.a;
     writeln(var);
     alias B = JavaStyleGinormousName;
     auto var2 = B.a;
     writeln(var2);
 }
 ```

 This makes everything explicit, with no surprises and no 
 additional learning curve for the new user. This proposal 
 essentially boils down to an implicit

 ```
 alias $. = [something inferred by the compiler depending on the 
 context
 ```
alias $identifier = ExpectedType.identifier; Your example above would still need the enum type names except you could write: JavaStyleGinormousName var = $a; The type name can be omitted for e.g. a function call, but then you can omit the types when passing a function literal to a typed function pointer parameter. Are you against function literal type inference too? The fact this feature is showing up in other systems languages is evidence it is useful.
Nov 18 2022
parent reply bachmeier <no spam.net> writes:
On Friday, 18 November 2022 at 21:27:51 UTC, Nick Treleaven wrote:
 On Friday, 18 November 2022 at 18:32:44 UTC, bachmeier wrote:
 ```
 import std;

 enum JavaStyleGinormousName { a, b, c, d}

 void main() {
     auto var = JavaStyleGinormousName.a;
     writeln(var);
     alias B = JavaStyleGinormousName;
     auto var2 = B.a;
     writeln(var2);
 }
 ```

 This makes everything explicit, with no surprises and no 
 additional learning curve for the new user. This proposal 
 essentially boils down to an implicit

 ```
 alias $. = [something inferred by the compiler depending on 
 the context
 ```
alias $identifier = ExpectedType.identifier; Your example above would still need the enum type names except you could write: JavaStyleGinormousName var = $a; The type name can be omitted for e.g. a function call, but then you can omit the types when passing a function literal to a typed function pointer parameter. Are you against function literal type inference too?
I'm not following. If I pull out the example from the `Case statements` example and fix it so it runs, I can do this without any changes to the language, but I'll grant that it requires typing one extra character: ``` import std.stdio: writeln; enum WordLetterOfTheDay{ a,b,c,d/*...*/ } alias w=WordLetterOfTheDay; void main(){ auto letterToday = w.b; import std.stdio; switch(letterToday){ case w.a: writeln("Apple"); break; case w.b: writeln("Bicycle"); break; case w.c: writeln("Caterpillar"); break; case w.d: writeln("Didgeridoo"); break; default: break; /*...*/ } } ``` And you can still use the more verbose name if you want. I don't see the benefit from adding extreme levels of complexity to the language. I do see someone checking out the language, seeing this, laughing, and never looking at D again.
 The fact this feature is showing up in other systems languages 
 is evidence it is useful.
Maybe. They're different languages.
Nov 18 2022
parent Nick Treleaven <nick geany.org> writes:
On Friday, 18 November 2022 at 22:47:19 UTC, bachmeier wrote:
 On Friday, 18 November 2022 at 21:27:51 UTC, Nick Treleaven 
 wrote:
 The type name can be omitted for e.g. a function call, but 
 then you can omit the types when passing a function literal to 
 a typed function pointer parameter. Are you against function 
 literal type inference too?
I'm not following.
I'm saying that the type inference works essentially the same as function literal type inference: ```d enum LongName { a,b,c } LongName e; void function(int) f; void main() { f = (int i){}; f = (i){}; // infer parameter type e = LongName.a; e = $a; // infer parent type } ``` Given that inference is simple in both cases, why disallow it in only one?
 If I pull out the example from the `Case statements` example 
 and fix it so it runs, I can do this without any changes to the 
 language, but I'll grant that it requires typing one extra 
 character:

 ```
 import std.stdio: writeln;

 enum WordLetterOfTheDay{ a,b,c,d/*...*/ }
 alias w=WordLetterOfTheDay;
That alias is a good enough solution for a switch case with multiple case statements. It is however worse than the status quo when doing an assignment to a variable, because then you don't need to write the type again so a single use alias is not helping.
 The fact this feature is showing up in other systems languages 
 is evidence it is useful.
Maybe. They're different languages.
Yes, though we have no way to avoid writing the type again for single uses.
Nov 19 2022
prev sibling next sibling parent Paul Backus <snarwin gmail.com> writes:
Continuing discussion from the feedback thread:

On Friday, 18 November 2022 at 17:19:11 UTC, IchorDev wrote:
 I presume this means that the list of cases must therefore be 
 exhaustive?
More or less, yes. That doesn't necessarily mean you have to list every possible context where ETI could be used one by one. A better approach might be to come up with a set of general, context-independent rules that specify how `$identifier` is evaluated, and then add special cases only as necessary to cover situations where the rules don't apply.
 I might need help from some experienced implementers to work 
 through that, since there are probably many aspects of D's 
 syntax that I am unfamiliar with. For instance, mixing enum 
 types with `int`s in an array literal causes it to be `int[]`. 
 Should ETI work in that case? The easy answer is "no". However, 
 what if D already has a mechanism for figuring out what types 
 have already been used in an array literal? If so, then ETI 
 could work in that example without a special-case, 
 unambiguously.
I'm sure there are many people in the D community who would be happy to help you answer questions like these. Ultimately, though, it is your responsibility as the DIP author to make sure that those questions are addressed before the DIP is submitted to Walter and Atila for formal assessment. If you feel you lack the experience to do this, you might consider recruiting someone more experienced as a co-author.
Nov 18 2022
prev sibling next sibling parent reply Adam D Ruppe <destructionator gmail.com> writes:
Lemme propose a generalization of the concept and an alternative 
syntax.

Consider the following code:

```
class ListBox {
    static struct Option {
          enum Type { Thing }
          Type type;
          string displayText;
    }

    void addOption(Option o) {}
}

ListBox b;

b.addOption(auto(auto.Thing, "foo"));
```


ok so what happens there is the pseudo-namespace auto refers to 
the type of the parameter. is is essentially magic `alias auto = 
typeof(arg);`

first layer i call the constructor, auto(...) is constructing a 
ListBox.Option, which it knows because that's what `addOption` 
takes, so that `auto` is just aliasing that name. The parens 
after it call the ctor exactly the same as if you wrote out 
`ListBox.Option`.

now that constructor takes a ListBox.Option.Type, so the auto 
used in *that* function call refers to *that*, just like your 
enum.

But it isn't limited to just enums.


This would also potentially work in return statements and assign 
expressions.

The type would have to be 100% unambiguous - the function must 
not be overloaded (well except maybe on arity) - so we avoid all 
that complication. Wouldn't work for templates.

Possible thing though:

listbox.addOption(to!auto("some string"))

might be allowed to work, using auto as the alias of the 
unambiguous parameter type could allow this too. I don't find 
this as important of a case to consider though.


BTW I used the word `auto` cuz it is a common thing but it could 
just as well be anything else, it is just a magic temporary alias 
after all.
Nov 18 2022
parent Timon Gehr <timon.gehr gmx.ch> writes:
On 18.11.22 20:54, Adam D Ruppe wrote:
 
 BTW I used the word `auto` cuz it is a common thing but it could just as 
 well be anything else, it is just a magic temporary alias after all.
_ is pretty commonly used as a placeholder in other languages.
Nov 18 2022
prev sibling next sibling parent reply Walter Bright <newshound2 digitalmars.com> writes:
The wordy:

     with(myObj) with(Size) with(Shape) with(State)

indeed doesn't look appetizing. But we could address this with:

     with (myObj, Size, Shape, State)
Nov 18 2022
parent Per =?UTF-8?B?Tm9yZGzDtnc=?= <per.nordlow gmail.com> writes:
On Friday, 18 November 2022 at 21:12:54 UTC, Walter Bright wrote:
     with (myObj, Size, Shape, State)
Good idea.
Nov 18 2022
prev sibling next sibling parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 18.11.22 22:09, Walter Bright wrote:
 What happens in combination with function and template overloading is not
discussed.
It does not have to be.
 For example:
 
     enum A { a }
     enum B { a }
 
     void ket(A);
     void ket(B);
 
     ...
     ket(a);
     ...
 ...
Should be ket($a).
 That's the simplest case. More complex cases come when there are multiple
overloaded functions with diverse enum arguments, resulting in an unbounded
combinatorial problem of which combination of enum members will be selected.
 ...
This is just not true. Overloading introduces zero additional problems. D already has well-defined overloading rules. You only have to be able to match each function on its own.
 This kind of problem comes up whenever we contemplate adding top-down type
inference and try to make it work in combination with the current bottom up
method. It works in trivial cases as shown in the DIP, but the complex ones are
the problem.
Why "contemplate"? D already has such inference for delegates. ```d import std.stdio; enum A{ a, b, } enum B{ b, c, } void foo(A delegate(A) dg){ writeln("first overload"); } void foo(B delegate(B) dg){ writeln("second overload"); } void main(){ foo((x){ // first overload static if(__traits(hasMember,typeof(x),"a")) return typeof(x).a; }); /+foo((x){ // error, ambiguous static if(__traits(hasMember,typeof(x),"b")) return typeof(x).b; });+/ foo((x){ // second overload static if(__traits(hasMember,typeof(x),"c")) return typeof(x).c; }); } ``` It works just fine. Now just do literally the same thing for the new enum inference. Probably one can even reuse some of the compiler code.
 (Even worse than the function overloading problem is the template overloading
problem, as the compiler will need to instantiate the template with each
combination of enum inferences just to figure out what the type of the template
is.) 
Again, this has nothing to do with overloading. In any case, just do the same as for the delegate case and reject if there is no explicitly given enum type to pick up on in the function signature. Instantiating all combinations is never what the user expects.
Nov 18 2022
next sibling parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 11/18/2022 2:49 PM, Timon Gehr wrote:
 Should be ket($a).
Yah, I missed that. That does change how the lookups work from what I posted.
Nov 18 2022
parent reply Walter Bright <newshound2 digitalmars.com> writes:
Consider this:

     enum A { a; }
     enum B { a; }

     void f(A);
     void f(B);

     ...
     f($a + $a); // mentioned in the DIP as allowed
     ...

Since the DIP allows expressions containing such enum inferences, it looks like 
we are faced with the possibility of having to re-run the semantic pass for
enum 
arguments for every enum overload.
Nov 18 2022
next sibling parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 11/19/22 05:22, Walter Bright wrote:
 Consider this:
 
      enum A { a; }
      enum B { a; }
 
      void f(A);
      void f(B);
 
      ...
      f($a + $a); // mentioned in the DIP as allowed
      ...
 
 Since the DIP allows expressions containing such enum inferences, it 
 looks like we are faced with the possibility of having to re-run the 
 semantic pass for enum arguments for every enum overload.
Only if the new feature is actually used, and yes, this is the same as for function literals. I guess the implementation can be optimized further for enum arguments, but I doubt it would make a meaningful difference.
Nov 19 2022
parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 11/19/2022 4:22 AM, Timon Gehr wrote:
 On 11/19/22 05:22, Walter Bright wrote:
 Since the DIP allows expressions containing such enum inferences, it looks 
 like we are faced with the possibility of having to re-run the semantic pass 
 for enum arguments for every enum overload.
Only if the new feature is actually used,
Yes, but that would require a significant redo of the semantic routines, which modify the ASTs in-place.
Nov 19 2022
parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 20.11.22 04:20, Walter Bright wrote:
 On 11/19/2022 4:22 AM, Timon Gehr wrote:
 On 11/19/22 05:22, Walter Bright wrote:
 Since the DIP allows expressions containing such enum inferences, it 
 looks like we are faced with the possibility of having to re-run the 
 semantic pass for enum arguments for every enum overload.
Only if the new feature is actually used,
Yes, but that would require a significant redo of the semantic routines, which modify the ASTs in-place.
To some extent I think this is the case, but function literals already defer the semantic pass in some way, so it seems feasible.
Nov 20 2022
parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 11/20/2022 2:03 AM, Timon Gehr wrote:
 To some extent I think this is the case, but function literals already defer
the 
 semantic pass in some way, so it seems feasible.
True, and templates also make a copy of the AST before instantiating it. But: 1. template compilation is not known for speed or low memory consumption 2. every function argument would have to be copied first, as it wouldn't know about $ processing in advance (or have to make a pass over it first to detect it) 3. if there were, say, 5 occurrences of $a, each of that which could be 2 different instances to try, what's that, 32 copies I'm not too thrilled about this.
Nov 21 2022
next sibling parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 22.11.22 01:41, Walter Bright wrote:
 On 11/20/2022 2:03 AM, Timon Gehr wrote:
 To some extent I think this is the case, but function literals already 
 defer the semantic pass in some way, so it seems feasible.
True, and templates also make a copy of the AST before instantiating it. But: 1. template compilation is not known for speed or low memory consumption 2. every function argument would have to be copied first, as it wouldn't know about $ processing in advance (or have to make a pass over it first to detect it) ...
I guess the two-pass thing is how function literals work, so you'd do that?
 3. if there were, say, 5 occurrences of $a, each of that which could be 
 2 different instances to try, what's that, 32 copies
 
 I'm not too thrilled about this.
The DIP does not propose trying all combinations. You'd get number of function overloads copies for each occurrence of $a. It's not exponential and without overloading (I think this is the majority of cases in typical user code) it is one copy.
Nov 21 2022
parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 11/21/2022 5:19 PM, Timon Gehr wrote:
 I guess the two-pass thing is how function literals work, so you'd do that?
Function literals are pretty much treated as templates.
 The DIP does not propose trying all combinations. You'd get number of function 
 overloads copies for each occurrence of $a. It's not exponential and without 
 overloading (I think this is the majority of cases in typical user code) it is 
 one copy.
The combinatorics matter, they can't be done incrementally. But I suggest abandoning the ETI for overloaded functions.
Nov 23 2022
next sibling parent reply Stefan Koch <uplink.coder googlemail.com> writes:
On Wednesday, 23 November 2022 at 23:53:23 UTC, Walter Bright 
wrote:
 On 11/21/2022 5:19 PM, Timon Gehr wrote:
 I guess the two-pass thing is how function literals work, so 
 you'd do that?
Function literals are pretty much treated as templates.
 The DIP does not propose trying all combinations. You'd get 
 number of function overloads copies for each occurrence of $a. 
 It's not exponential and without overloading (I think this is 
 the majority of cases in typical user code) it is one copy.
The combinatorics matter, they can't be done incrementally. But I suggest abandoning the ETI for overloaded functions.
Strictly speaking the worst case combinatorics for overloaded `$` expressions is O(n * m) where n is the number of overloads, m is the number of distinct enum parameters in the same position. It's generally as demanding as as other overload resolutions. It's true that for ```C int f(EnumType1 e) { return 1; } int f(EnumType2 e) { return 2; } int f(EnumType3 e) { return 3; } pragma(msg, f($a)); ``` There will be at most 3 lookups into the enum member hash table, to check whether the member a collides. for ```C int f(EnumType1 e, EnumType2 e2) { return 1; } int f(EnumType2 e, EnumType1 e2) { return 2; } int f(EnumType3 e, EnumType3 e2) { return 3; } pragma(msg, f($a, $b)); ``` there will be 6 lookups in the worst case, (which is the success case). And it is possible to make these lookups cheaper than they are right now.
Nov 24 2022
parent Stefan Koch <uplink.coder googlemail.com> writes:
On Thursday, 24 November 2022 at 10:33:04 UTC, Stefan Koch wrote:

 Strictly speaking the worst case combinatorics for overloaded 
 `$` expressions is O(n * m) where n is the number of overloads, 
 m is the number of distinct enum parameters in the same 
 position.
Oops I used the words strictly speaking, that was wrong. Because the hash-table lookup could degenerate into a linear search. strictly speaking: it's O(n * m * k) where n is the number of overloads m is the sum of enum parameters in n k is sum of the number of enum members in the set of distinct enum types used by all overloads. But that's _highly_ unlikely. So, _generally_ speaking it's O(n * m). _strictly_ speaking it's O (n * m * k).
Nov 24 2022
prev sibling parent IchorDev <zxinsworld gmail.com> writes:
On Wednesday, 23 November 2022 at 23:53:23 UTC, Walter Bright 
wrote:
 I suggest abandoning the ETI for overloaded functions.
Then it's just downright inconsistent. If you don't want to deal with that, avoid using ETI with heavily overloaded functions. Just like with templates, you pay for what you use.
Nov 24 2022
prev sibling parent IchorDev <zxinsworld gmail.com> writes:
On Tuesday, 22 November 2022 at 00:41:54 UTC, Walter Bright wrote:
 3. if there were, say, 5 occurrences of $a, each of that which 
 could be 2 different instances to try, what's that, 32 copies

 I'm not too thrilled about this.
The moment you know there are 2 instances with different enum type parameters that both have an `a` member, you can return an error. Also why do you expect 2 functions to look up a member `a` in 5 different enums? Just limit the search to the enums in the function parameters.
Nov 21 2022
prev sibling parent reply IchorDev <zxinsworld gmail.com> writes:
On Saturday, 19 November 2022 at 04:22:39 UTC, Walter Bright 
wrote:
 Consider this:

     enum A { a; }
     enum B { a; }

     void f(A);
     void f(B);

     ...
     f($a + $a); // mentioned in the DIP as allowed
     ...

 Since the DIP allows expressions containing such enum 
 inferences, it looks like we are faced with the possibility of 
 having to re-run the semantic pass for enum arguments for every 
 enum overload.
If you're sure that arithmetic and ETI won't mix for implementation reasons then I could explicitly prohibit it. My only apprehension is that `OR`ing enum flags with ETI is very handy.
Nov 20 2022
parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 11/20/2022 8:25 AM, IchorDev wrote:
 If you're sure that arithmetic and ETI won't mix for implementation reasons
then 
 I could explicitly prohibit it. My only apprehension is that `OR`ing enum
flags 
 with ETI is very handy.
It is handy and used a lot.
Nov 21 2022
next sibling parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 22.11.22 01:42, Walter Bright wrote:
 On 11/20/2022 8:25 AM, IchorDev wrote:
 If you're sure that arithmetic and ETI won't mix for implementation 
 reasons then I could explicitly prohibit it. My only apprehension is 
 that `OR`ing enum flags with ETI is very handy.
It is handy and used a lot.
The way D does it, it also has some issues: enum E{ a=1, b=2, } void main(){ import std.stdio; writeln(E.a|E.b); // cast(E)3 } Some other languages require some annotation on the enum to indicate that it is to be used as flags and disallow arithmetic otherwise, writeln could pick that up also and format it nicely as a|b.
Nov 21 2022
parent Walter Bright <newshound2 digitalmars.com> writes:
On 11/21/2022 5:22 PM, Timon Gehr wrote:
 Some other languages require some annotation on the enum to indicate that it
is 
 to be used as flags and disallow arithmetic otherwise, writeln could pick that 
 up also and format it nicely as a|b.
It's not perfect, but at some point adding more complexity to try to fix it becomes a larger problem.
Nov 22 2022
prev sibling parent IchorDev <zxinsworld gmail.com> writes:
On Tuesday, 22 November 2022 at 00:42:43 UTC, Walter Bright wrote:
 On 11/20/2022 8:25 AM, IchorDev wrote:
 If you're sure that arithmetic and ETI won't mix for 
 implementation reasons then I could explicitly prohibit it. My 
 only apprehension is that `OR`ing enum flags with ETI is very 
 handy.
It is handy and used a lot.
OK so you have no issue with the arithmetic? Cool.
Nov 21 2022
prev sibling parent Dukc <ajieskola gmail.com> writes:
On Friday, 18 November 2022 at 22:49:33 UTC, Timon Gehr wrote:
 Why "contemplate"? D already has such inference for delegates.

 ```d
 import std.stdio;

 enum A{
     a,
     b,
 }
 enum B{
     b,
     c,
 }

 void foo(A delegate(A) dg){
     writeln("first overload");
 }
 void foo(B delegate(B) dg){
     writeln("second overload");
 }

 void main(){
     foo((x){ // first overload
         static if(__traits(hasMember,typeof(x),"a"))
             return typeof(x).a;
     });
     /+foo((x){ // error, ambiguous
         static if(__traits(hasMember,typeof(x),"b"))
             return typeof(x).b;
     });+/
     foo((x){ // second overload
         static if(__traits(hasMember,typeof(x),"c"))
             return typeof(x).c;
     });
 }
 ```

 It works just fine. Now just do literally the same thing for 
 the new enum inference. Probably one can even reuse some of the 
 compiler code.
Excellent observation, definitely did not occur to me! IMO this would greatly increase the appeal of this DIP. It can sidestep many of the difficult questions about corner cases with complex expressions.
Nov 19 2022
prev sibling next sibling parent reply Ki Rill <rill.ki yahoo.com> writes:
On Friday, 18 November 2022 at 15:37:31 UTC, Mike Parker wrote:

 [...]
I think it's not worth adding this to D as well. I have no problem typing out the full name of an enum, and if I or anyone else does face such a difficulty, why not use a short alias? ``` with(a, b, c, d): ``` That's a good idea.
Nov 18 2022
next sibling parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 19.11.22 02:04, Ki Rill wrote:
 On Friday, 18 November 2022 at 15:37:31 UTC, Mike Parker wrote:

 [...]
I think it's not worth adding this to D as well. I have no problem typing out the full name of an enum, and if I or anyone else does face such a difficulty, why not use a short alias? ``` with(a, b, c, d): ``` That's a good idea.
I think this is a little thing that most competing languages have and people are confused that D does not have it.
Nov 18 2022
parent IchorDev <zxinsworld gmail.com> writes:
On Saturday, 19 November 2022 at 01:46:48 UTC, Timon Gehr wrote:
 I think this is a little thing that most competing languages 
 have and people are confused that D does not have it.
Yeah, I was pretty confused when I discovered that Swift—the king of utterly overkill verbose syntax—had enum type inference... but not D?
Nov 20 2022
prev sibling parent reply ryuukk_ <ryuukk.dev gmail.com> writes:
On Saturday, 19 November 2022 at 01:04:39 UTC, Ki Rill wrote:
 On Friday, 18 November 2022 at 15:37:31 UTC, Mike Parker wrote:

 [...]
I think it's not worth adding this to D as well. I have no problem typing out the full name of an enum, and if I or anyone else does face such a difficulty, why not use a short alias? ``` with(a, b, c, d): ``` That's a good idea.
```D MySuperLongType flag = MySuperLongType.ValueA | MySuperLongType.ValueB | MySuperLongType.ValueC | MySuperLongType.ValueD | MySuperLongType.ValueE | MySuperLongType.ValueF | MySuperLongType.ValueG; // vs MySuperLongType flag = .ValueA | .ValueB | .ValueC | .ValueD | .ValueE | .ValueF | .ValueG; ``` No need to import any helper function, no need to introduce any extra noisy variable, no need to bloat the scope with `with` or alias, it's simple, readable, and effective Have you ever tried Vulkan? (graphics library) The amount of ugly code one has to write due to verbose enum/struct name is disgusting Also D already supports designated initialization for structs, it's kinda similar in principle, and it is super useful
Nov 18 2022
next sibling parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 11/18/2022 6:06 PM, ryuukk_ wrote:
 MySuperLongType flag = MySuperLongType.ValueA | MySuperLongType.ValueB | 
 MySuperLongType.ValueC | MySuperLongType.ValueD | MySuperLongType.ValueE | 
 MySuperLongType.ValueF | MySuperLongType.ValueG;
 
 // vs
 
 MySuperLongType flag = .ValueA | .ValueB | .ValueC | .ValueD | .ValueE |
.ValueF 
 | .ValueG;
with (MySuperLongType) MySuperLongType flag = ValueA | ValueB | ValueC | ValueD | ValueE | ValueF | ValueG;
Nov 18 2022
next sibling parent reply Adam D. Ruppe <destructionator gmail.com> writes:
On Saturday, 19 November 2022 at 02:57:27 UTC, Walter Bright 
wrote:
 with (MySuperLongType)
 MySuperLongType flag = ValueA | ValueB | ValueC | ValueD | 
 ValueE | ValueF | ValueG;
`flag` is now inaccessible since `with` creates a new scope. Of course, you may be able to just extend the scope to cover the usage point as well.
Nov 18 2022
next sibling parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 11/18/2022 7:09 PM, Adam D. Ruppe wrote:
 On Saturday, 19 November 2022 at 02:57:27 UTC, Walter Bright wrote:
 with (MySuperLongType)
 MySuperLongType flag = ValueA | ValueB | ValueC | ValueD | ValueE | ValueF | 
 ValueG;
`flag` is now inaccessible since `with` creates a new scope.
True, but you could also do: with (MySuperLongType): // <= note colon MySuperLongType flag = ValueA | ValueB | ValueC | ValueD | ValueE | ValueF | ValueG;
 Of course, you may be able to just extend the scope to cover the usage point
as 
 well.
Yup.
Nov 18 2022
parent reply Adam D Ruppe <destructionator gmail.com> writes:
On Saturday, 19 November 2022 at 03:46:55 UTC, Walter Bright 
wrote:
 True, but you could also do:

 with (MySuperLongType):  // <= note colon
 MySuperLongType flag = ValueA | ValueB | ValueC | ValueD | 
 ValueE | ValueF |
  ValueG;
Something I do before making a post is to run it through the compiler to ensure it actually works like I'm claiming it works. You should do this too. The colon form is only valid outside functions, not inside them*. Inside a function, you need to use the {} form. (btw my experience with the colon form outside functions tends to be regret anyway so I very rarely use it anymore anyway.) * well ok, you can put a nested aggregate inside a function and that's kinda still inside a function. but you know what i mean, i think the grammar calls it a declaration context vs a statement context but i forget the formal words.
Nov 19 2022
parent Walter Bright <newshound2 digitalmars.com> writes:
On 11/19/2022 5:01 AM, Adam D Ruppe wrote:
 Something I do before making a post is to run it through the compiler to
ensure 
 it actually works like I'm claiming it works. You should do this too.
True.
Nov 19 2022
prev sibling parent IchorDev <zxinsworld gmail.com> writes:
On Saturday, 19 November 2022 at 03:09:26 UTC, Adam D. Ruppe 
wrote:
 On Saturday, 19 November 2022 at 02:57:27 UTC, Walter Bright 
 wrote:
 with (MySuperLongType)
 MySuperLongType flag = ValueA | ValueB | ValueC | ValueD | 
 ValueE | ValueF | ValueG;
`flag` is now inaccessible since `with` creates a new scope. Of course, you may be able to just extend the scope to cover the usage point as well.
This is why I actually avoid `with` to some degree. For the everyday occurrences of enums in constructors and function args scattered all over my code it's not useful compared to omitting the enum type... in fact it's just worse, so I also haven't found many great situations to use `with` for either.
Nov 20 2022
prev sibling next sibling parent ryuukk_ <ryuukk.dev gmail.com> writes:
On Saturday, 19 November 2022 at 02:57:27 UTC, Walter Bright 
wrote:
 On 11/18/2022 6:06 PM, ryuukk_ wrote:
 MySuperLongType flag = MySuperLongType.ValueA | 
 MySuperLongType.ValueB | MySuperLongType.ValueC | 
 MySuperLongType.ValueD | MySuperLongType.ValueE | 
 MySuperLongType.ValueF | MySuperLongType.ValueG;
 
 // vs
 
 MySuperLongType flag = .ValueA | .ValueB | .ValueC | .ValueD | 
 .ValueE | .ValueF | .ValueG;
with (MySuperLongType) MySuperLongType flag = ValueA | ValueB | ValueC | ValueD | ValueE | ValueF | ValueG;
Why should i have to type the name of the type twice? it doesn't help with readability Imagine on this small example, that would be overkill Little experiment, read it out loud, the repetition and noise is clearly not wanted ```D NetworkState network_state = NetworkSate.DISCONNECTED; ``` Another example: ```D if (client.network_state == NetworkState.CONNECTED) client.network_state = NetworkState.DISCONNECTED; // vs with (NetworkState) if (client.network_state == CONNECTED) client.network_state = DISCONNECTED; // same issue as above, reading it feels repetitive, and it adds extra cognitive load // there, straith to the point // you can name your variable more verbosely, you no longer have to duplicate enum type everywhere // type system is smart enough if (client.network_state == .CONNECTED) client.network_state = .DISCONNECTED; ``` Taken from my project, c'mon, if i use proper naming in my code, i should be allowed to ommit the typename of the enum Just like i can omit the type of the integer ```D int myInt = 42; // and not int myInt = int.42; ``` ```D if (ctx.engine.input.is_key_just_pressed(.PAGE_UP)) { cam_pos_d *= 1.2; cam_pos_h *= 1.2; } ```
Nov 18 2022
prev sibling parent reply Dukc <ajieskola gmail.com> writes:
On Saturday, 19 November 2022 at 02:57:27 UTC, Walter Bright 
wrote:
 On 11/18/2022 6:06 PM, ryuukk_ wrote:
 MySuperLongType flag = MySuperLongType.ValueA | 
 MySuperLongType.ValueB | MySuperLongType.ValueC | 
 MySuperLongType.ValueD | MySuperLongType.ValueE | 
 MySuperLongType.ValueF | MySuperLongType.ValueG;
 
 // vs
 
 MySuperLongType flag = .ValueA | .ValueB | .ValueC | .ValueD | 
 .ValueE | .ValueF | .ValueG;
with (MySuperLongType) MySuperLongType flag = ValueA | ValueB | ValueC | ValueD | ValueE | ValueF | ValueG;
Since with creates a new scope, it would have to be ```D auto flag = { with(MySuperLongType) return ValueA | ValueB | ValueC | ValueD | ValueE | ValueF | ValueG; }(); ``` Still a lot better than repeating `MySuperLongType` for each member IMO, but ugly enough that this DIP would be an improvement.
Nov 19 2022
parent reply Andrey Zherikov <andrey.zherikov gmail.com> writes:
On Saturday, 19 November 2022 at 08:33:50 UTC, Dukc wrote:
 Since with creates a new scope, it would have to be

 ```D
 auto flag = { with(MySuperLongType) return
      ValueA | ValueB | ValueC | ValueD
      | ValueE | ValueF | ValueG;
 }();
 ```

 Still a lot better than repeating `MySuperLongType` for each 
 member IMO, but ugly enough that this DIP would be an 
 improvement.
Will this be better if it's supported? ```d auto flag = with(MySuperLongType) ValueA | ValueB | ValueC | ValueD | ValueE | ValueF | ValueG; ```
Nov 19 2022
parent Dukc <ajieskola gmail.com> writes:
On Saturday, 19 November 2022 at 08:44:34 UTC, Andrey Zherikov 
wrote:
 Will this be better if it's supported?
 ```d
 auto flag = with(MySuperLongType)
             ValueA | ValueB | ValueC | ValueD | ValueE | ValueF 
 | ValueG;
 ```
I'd like that sure! In this case yes IMO. The proposed syntax is still better though when you reassign to an already declared value. ```D flag &= $.ValueA | $.ValueC; ``` Whether that's a strong enough case to implement the proposal alongside expression `with`s, is another question. I haven't decided my opinion yet.
Nov 19 2022
prev sibling next sibling parent reply bachmeier <no spam.net> writes:
On Saturday, 19 November 2022 at 02:06:57 UTC, ryuukk_ wrote:
 ```D
 MySuperLongType flag = MySuperLongType.ValueA | 
 MySuperLongType.ValueB | MySuperLongType.ValueC | 
 MySuperLongType.ValueD | MySuperLongType.ValueE | 
 MySuperLongType.ValueF | MySuperLongType.ValueG;

 // vs

 MySuperLongType flag = .ValueA | .ValueB | .ValueC | .ValueD | 
 .ValueE | .ValueF | .ValueG;
 ```
Very, very simple solution: ``` MySuperLongType flag = M.ValueA | M.ValueB | M.ValueC | M.ValueD | M.ValueE | M.ValueF | M.ValueG; ``` I mean, if you don't want to type that much, use shorter names.
Nov 18 2022
parent ryuukk_ <ryuukk.dev gmail.com> writes:
On Saturday, 19 November 2022 at 03:15:26 UTC, bachmeier wrote:
 On Saturday, 19 November 2022 at 02:06:57 UTC, ryuukk_ wrote:
 ```D
 MySuperLongType flag = MySuperLongType.ValueA | 
 MySuperLongType.ValueB | MySuperLongType.ValueC | 
 MySuperLongType.ValueD | MySuperLongType.ValueE | 
 MySuperLongType.ValueF | MySuperLongType.ValueG;

 // vs

 MySuperLongType flag = .ValueA | .ValueB | .ValueC | .ValueD | 
 .ValueE | .ValueF | .ValueG;
 ```
Very, very simple solution: ``` MySuperLongType flag = M.ValueA | M.ValueB | M.ValueC | M.ValueD | M.ValueE | M.ValueF | M.ValueG; ``` I mean, if you don't want to type that much, use shorter names.
Using shorter type/variable name is what hurts readability of your code Using proper naming is the key, if i can omit the type name of the enum and leverage the type system, i am encouraged to use meaningful and longer type/variable name, wich improve readability ```D // the function name is verbose, i know it passes the enumeration type of keys is_key_pressed(.A); is_key_pressed(Key.A); // vs // the function name is short, what should i pass? // of you passed and enumeration type of keys // therefore you ask if it's a key that was pressed is_pressed(.A); is_pressed(Key.A); ``` I should have the choice
Nov 18 2022
prev sibling parent IchorDev <zxinsworld gmail.com> writes:
On Saturday, 19 November 2022 at 02:06:57 UTC, ryuukk_ wrote:
 Have you ever tried Vulkan? (graphics library)

 The amount of ugly code one has to write due to verbose 
 enum/struct name is disgusting

 Also D already supports designated initialization for structs, 
 it's kinda similar in principle, and it is super useful
I've run into cases like this a LOT. C library bindings that have enums with ridiculously long redundant names like `vegetable_t.vegetable_carrot` are abundant. Also yes I've used Vulkan's API... never again. My head still hurts.
Nov 20 2022
prev sibling next sibling parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 19.11.22 03:54, Walter Bright wrote:
 With the syntax $e to look up an enum member, the compiler will need to search
*every* enum that is in scope. Since one of D's strengths is whole program
compilation, this can be slow. To speed that up, it will likely require that
the compiler maintain a hash table of all the enum fields.
 
 I.e. a parallel symbol table will have to be maintained alongside the regular
symbol table. 
Not true. E.g. see my example with delegates.
Nov 18 2022
parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 11/18/2022 7:05 PM, Timon Gehr wrote:
 On 19.11.22 03:54, Walter Bright wrote:
 With the syntax $e to look up an enum member, the compiler will need to search 
 *every* enum that is in scope. Since one of D's strengths is whole program 
 compilation, this can be slow. To speed that up, it will likely require that 
 the compiler maintain a hash table of all the enum fields.

 I.e. a parallel symbol table will have to be maintained alongside the regular 
 symbol table. 
Not true. E.g. see my example with delegates.
I was thinking of the general case of $a being able to find member `a` among all the enums in scope. You're referring, of course, to the "contextual" part of the DIP, where the lookup works only in a subset of cases. The contextual lookup can result in some odd cases like: ---- module A ---- private enum E { e; }; public void dra(E); ------------------ import A; dra($e); ------------------ Is that a good thing? I'm not sure. This is also not addressed in the DIP.
Nov 18 2022
next sibling parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 19.11.22 05:14, Walter Bright wrote:
 
 You're referring, of course, to the "contextual" part of the DIP, where 
 the lookup works only in a subset of cases. The contextual lookup can 
 result in some odd cases like:
 
 ---- module A ----
      private enum E { e; };
      public void dra(E);
 ------------------
      import A;
 
      dra($e);
 ------------------
 ...
This is a good point. However, it's an existing oddity in the language that public symbols can use private symbols in their signatures.
 Is that a good thing?
I think contextual lookup is better than trying to do a lookup within the scopes of all visible enumerations. Vladimir's suggestion where we would add symbol literals is even better. I have somewhat mixed feelings about implicit `with`. On one hand, it's even more convenient than `$e` `_.e`, `:e` etc, but on the other hand it's even less predictable for a user where it will work, and it can shadow variables from outer scopes (which is also a breaking change).
 I'm not sure. This is also not addressed in the DIP.
I don't have particularly strong feelings about this feature either way, but it is quite popular and I have been annoyed by the need to write `with` statements in the past. (But maybe that's partly because the emacs d mode is not so great at indenting switch(x) with(E){ case a: ... }.)
Nov 20 2022
parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 11/20/2022 1:56 AM, Timon Gehr wrote:
 I have somewhat mixed feelings about implicit `with`. On one hand, it's even 
 more convenient than `$e` `_.e`, `:e` etc, but on the other hand it's even
less 
 predictable for a user where it will work, and it can shadow variables from 
 outer scopes (which is also a breaking change).
Consider that we already have implicit with for field access within non-static member functions. I.e. `a` instead of `this.a`. Nobody has complained about it shadowing. But yes, it would be a (small) breaking change.
Nov 20 2022
next sibling parent Timon Gehr <timon.gehr gmx.ch> writes:
On 20.11.22 22:32, Walter Bright wrote:
 On 11/20/2022 1:56 AM, Timon Gehr wrote:
 I have somewhat mixed feelings about implicit `with`. On one hand, 
 it's even more convenient than `$e` `_.e`, `:e` etc, but on the other 
 hand it's even less predictable for a user where it will work, and it 
 can shadow variables from outer scopes (which is also a breaking change).
Consider that we already have implicit with for field access within non-static member functions. I.e. `a` instead of `this.a`. Nobody has complained about it shadowing.
It's in a nested scope, so that's more expected.
 
 But yes, it would be a (small) breaking change.
Well, I'd be happy to retire some of my with statements.
Nov 20 2022
prev sibling next sibling parent reply Adam D Ruppe <destructionator gmail.com> writes:
On Sunday, 20 November 2022 at 21:32:16 UTC, Walter Bright wrote:
 Nobody has complained about it shadowing.
Look at the yellow box a few paragraphs down here: http://dpldocs.info/this-week-in-d/Blog.Posted_2021_02_15.html#tip-of-the-week
 But yes, it would be a (small) breaking change.
Nov 20 2022
parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 11/20/2022 1:47 PM, Adam D Ruppe wrote:
 On Sunday, 20 November 2022 at 21:32:16 UTC, Walter Bright wrote:
 Nobody has complained about it shadowing.
Look at the yellow box a few paragraphs down here: http://dpldocs.info/this-week-in-d/Blog.Posted_2021_02_15.html#tip-of-the-week
I did those classes because at the time it seemed that our target was Java developers. This has since proved to be incorrect, and I wouldn't do them again. But they don't seem to be any harm.
Nov 21 2022
next sibling parent rikki cattermole <rikki cattermole.co.nz> writes:
On 22/11/2022 1:46 PM, Walter Bright wrote:
 I did those classes because at the time it seemed that our target was 
 Java developers. This has since proved to be incorrect, and I wouldn't 
 do them again. But they don't seem to be any harm.
As someone who did in fact come from Java prior to D, I can say I have in the past appreciated they existed even if I didn't use them much. Now if only we could do the same with structs ala Voldemort types...
Nov 21 2022
prev sibling parent reply Adam D Ruppe <destructionator gmail.com> writes:
On Tuesday, 22 November 2022 at 00:46:40 UTC, Walter Bright wrote:
 I did those classes because at the time it seemed that our 
 target was Java developers. This has since proved to be 
 incorrect, and I wouldn't do them again. But they don't seem to 
 be any harm.
Oh they're really nice and I use them a lot. But the variable shadowing due to the implicit `with(this)` can be quite a surprise, including some spooky action at a distance (adding something to the base class can erase a local variable from existence in an entirely different project!)
Nov 21 2022
parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 11/21/2022 4:59 PM, Adam D Ruppe wrote:
 But the variable shadowing due to the implicit `with(this)` can be quite a 
 surprise, including some spooky action at a distance (adding something to the 
 base class can erase a local variable from existence in an entirely different 
 project!)
It's the old tradeoff problem. You can make the bathroom bigger or the closet bigger, but not both.
Nov 22 2022
parent reply Adam D Ruppe <destructionator gmail.com> writes:
On Tuesday, 22 November 2022 at 18:13:00 UTC, Walter Bright wrote:
 It's the old tradeoff problem. You can make the bathroom bigger 
 or the closet bigger, but not both.
my point is just your statement that nobody ever complained about implicit(this) is demonstrably false.
Nov 22 2022
parent Walter Bright <newshound2 digitalmars.com> writes:
On 11/22/2022 10:25 AM, Adam D Ruppe wrote:
 On Tuesday, 22 November 2022 at 18:13:00 UTC, Walter Bright wrote:
 It's the old tradeoff problem. You can make the bathroom bigger or the closet 
 bigger, but not both.
my point is just your statement that nobody ever complained about implicit(this) is demonstrably false.
There's always somebody :-)
Nov 22 2022
prev sibling parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 20.11.22 22:32, Walter Bright wrote:
 
 But yes, it would be a (small) breaking change.
I really wouldn't want to run into this: ```d enum Role{ guest, member, developer, } void main(){ Role r; writeln(r); // error } ``` Too messy for me, but up to you.
Nov 20 2022
next sibling parent Timon Gehr <timon.gehr gmx.ch> writes:
On 20.11.22 22:58, Timon Gehr wrote:
 On 20.11.22 22:32, Walter Bright wrote:
 But yes, it would be a (small) breaking change.
I really wouldn't want to run into this: ```d enum Role{     guest,     member,     developer, } void main(){     Role r;     writeln(r); // error } ``` Too messy for me, but up to you.
Actually, I think with the current implementation of writeln this will work (subject to break at any time), but not this: ```d enum Role{ guest, member, developer, } void main(){ Role r; string s=to!string(r); // error } ``` Not a big fan of making local variable names part of the public API.
Nov 20 2022
prev sibling parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 11/20/2022 1:58 PM, Timon Gehr wrote:
 On 20.11.22 22:32, Walter Bright wrote:
 But yes, it would be a (small) breaking change.
I really wouldn't want to run into this: ```d enum Role{     guest,     member,     developer, } void main(){     Role r;     writeln(r); // error } ``` Too messy for me, but up to you.
I'm not seeing where the shadowing is?
Nov 21 2022
parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 22.11.22 01:49, Walter Bright wrote:
 On 11/20/2022 1:58 PM, Timon Gehr wrote:
 On 20.11.22 22:32, Walter Bright wrote:
 But yes, it would be a (small) breaking change.
I really wouldn't want to run into this: ```d enum Role{      guest,      member,      developer, } void main(){      Role r;      writeln(r); // error
(Should perhaps be auto s = to!string(r);)
 }
 ```

 Too messy for me, but up to you.
I'm not seeing where the shadowing is?
That's indeed basically the point. It's invisible. The implementation of to!string for enums has some code like this: switch(e){ foreach(member; EnumMembers!E){ case member: ... } } https://github.com/dlang/phobos/blob/master/std/conv.d#L1065-L1070 This is where the shadowing happens. You then get an compile error in the guts of Phobos. (I originally thought writeln would break due to that issue, but it's not using the same code: https://github.com/dlang/phobos/blob/master/std/format/internal/write.d#L3023-L3025 I am not fully sure if this will break with implicit with, but I think the DIP would allow $val here if the enum has a "val" member. So if you want to cover an equal amount of ground to the DIP, this will actually break too.) I think spilling the implementation details of library code into user code like that is a no-go.
Nov 21 2022
parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 11/21/2022 5:41 PM, Timon Gehr wrote:
 On 22.11.22 01:49, Walter Bright wrote:
 On 11/20/2022 1:58 PM, Timon Gehr wrote:
 On 20.11.22 22:32, Walter Bright wrote:
 But yes, it would be a (small) breaking change.
I really wouldn't want to run into this: ```d enum Role{      guest,      member,      developer, } void main(){      Role r;      writeln(r); // error
(Should perhaps be auto s = to!string(r);)
 }
 ```

 Too messy for me, but up to you.
I'm not seeing where the shadowing is?
That's indeed basically the point. It's invisible.
This code: --- import std.stdio; enum Role{ guest, member, developer, } void main(){ Role r; writeln(r); // error } --- compiles successfully and when run prints: guest
Nov 22 2022
next sibling parent reply Adam D Ruppe <destructionator gmail.com> writes:
On Tuesday, 22 November 2022 at 18:16:43 UTC, Walter Bright wrote:
 compiles successfully and when run prints:
Did you implement the implicit with? The point is that proposal will introduce a regression with that code.
Nov 22 2022
parent Walter Bright <newshound2 digitalmars.com> writes:
On 11/22/2022 10:26 AM, Adam D Ruppe wrote:
 On Tuesday, 22 November 2022 at 18:16:43 UTC, Walter Bright wrote:
 compiles successfully and when run prints:
Did you implement the implicit with? The point is that proposal will introduce a regression with that code.
I am not seeing where or how.
Nov 22 2022
prev sibling parent reply Steven Schveighoffer <schveiguy gmail.com> writes:
On 11/22/22 1:16 PM, Walter Bright wrote:
 On 11/21/2022 5:41 PM, Timon Gehr wrote:
 On 22.11.22 01:49, Walter Bright wrote:
 On 11/20/2022 1:58 PM, Timon Gehr wrote:
 On 20.11.22 22:32, Walter Bright wrote:
 But yes, it would be a (small) breaking change.
I really wouldn't want to run into this: ```d enum Role{      guest,      member,      developer, } void main(){      Role r;      writeln(r); // error
(Should perhaps be auto s = to!string(r);)
 }
 ```

 Too messy for me, but up to you.
I'm not seeing where the shadowing is?
That's indeed basically the point. It's invisible.
This code: --- import std.stdio; enum Role{      guest,      member,      developer, } void main(){      Role r;      writeln(r); // error } --- compiles successfully and when run prints: guest
To spell it out, when you write `case member:` what does `member` refer to? It currently, in the implementation of Phobos refers to the `member` iteration variable of the foreach inside to!string: ```d foreach(member; EnumMembers!E) { ``` But if an implicit `with(Role)` is added to the case clause, now it only ever refers to `Role.member`. Essentially, you will end up with a switch that looks like: ```d switch(e) { case Role.member: ... case Role.member: ... case Role.member: ... default: ... } ``` Which will then be a compiler error. The fix would be to rename the iteration variable to something the user couldn't possibly use. It's not pretty. -Steve
Nov 22 2022
parent reply Quirin Schroll <qs.il.paperinik gmail.com> writes:
On Wednesday, 23 November 2022 at 03:24:30 UTC, Steven 
Schveighoffer wrote:
 [snip]

 But if an implicit `with(Role)` is added to the case clause, 
 now it only ever refers to `Role.member`. Essentially, you will 
 end up with a switch that looks like:

 ```d
 switch(e) {
    case Role.member: ...
    case Role.member: ...
    case Role.member: ...
    default: ...
 }
 ```

 Which will then be a compiler error.

 The fix would be to rename the iteration variable to something 
 the user couldn't possibly use. It's not pretty.
TL;DR: Use a version of `with` that matches lazily, i.e. when the identifier resolved to nothing else, and not greedily as the current one. [End of TL;DR] Best thing is, `lazy` is already an aptly named keyword and can be combined with `with` to form `lazy with` (same as `static` and `if` or `foreach` or `assert` combine to effectively two-word keywords). The problem is that `with(expr)` is greedy: If it can resolve an identifier `ident` as `expr.ident`, it will take it and not give it up even if that leads to a fail. (Like Regex greedy matching, thus the name.) The implicit `with` must be lazy to be useful: If `ident` cannot be resolved otherwise, in the context of `lazy with(arg)` an attempt for `arg.ident` is made. In the above code, even if `Role` has a member named `member`, the function local `member` is considered: ```d import std.stdio; enum Role { guest, member, developer, } void main() { Role r; lazy with (typeof(r)) // implicitly added? switch(r) { static foreach(member; EnumMembers!Role ) { case member: // sees foreach variable, therefore lazy with does nothing. ... } } lazy with (typeof(r)) // implicitly added? switch(r) { case guest: // as no other `guest` in scope, lazy with makes it Role.guest ... case member: // as no other `member` in scope, lazy with makes it Role.member ... } } ``` If I’m not missing something, the only sad case is this: ```d immutable member = Role.developer; // Who does this anyways? lazy with (typeof(r)) switch(r) { case guest: // lazy with makes it Role.guest ... case member: // `member` in scope, effectively Role.developer. ... } ``` The same can be done for declarations without `auto` and maybe assignments: ```d Role r = member; r = guest; ``` is as if: ```d Role r = () { lazy with(Role) return member; }(); lvalueExpresson = () { lazy with(typeof(lvalueExpresson)) return guest; }(); // maybe? ``` I guess declarations are unproblematic. For assignments, it might be surprising because lvalue expressions can be complex and a reminder for the type might be appropriate. On the other hand, if that’s the case, nothing stops you from being explicit. Another issue with assignment expressions is that not all left-hand side expressions have a type: Property setters and opIndexAssign don’t trivially give you the supposed right-hand side type. The type might even be a template type parameter. It’s a best effort solution at best.
Nov 23 2022
parent Quirin Schroll <qs.il.paperinik gmail.com> writes:
On Wednesday, 23 November 2022 at 09:38:06 UTC, Quirin Schroll 
wrote:
 If `ident` cannot be resolved otherwise, in the context of 
 `lazy with(arg)` an attempt for `arg.ident` is made.
A reasonable and intentional, yet noteworthy consequence is that nested `lazy with` resolving is reversed compared to regular `with`: ```d enum A { x, y } enum B { x, y } void main() { with (A) with (B) { pragma(msg, typeof(x)); // B } lazy with (A) lazy with (B) { pragma(msg, typeof(x)); // A } } ``` Essentially, when resolving `x`, in the first case, `with(B)` goes ahead and resolves it (greedily). `with(A)` has nothing to do. In the second case, `lazy with(B)` asks its surrounding context if it can resolve `x` and `lazy with(A)` then does the same. The answer for `lazy with(A)` is that no `x` is in scope, thus it attempts to resolve `x` as `A.x` and succeeds. Finally, `lazy with(B)` has no identifiers to resolve.
Nov 23 2022
prev sibling parent reply IchorDev <zxinsworld gmail.com> writes:
On Saturday, 19 November 2022 at 04:14:18 UTC, Walter Bright 
wrote:
 Is that a good thing? I'm not sure. This is also not addressed 
 in the DIP.
Well `dra(E.e);` doesn't compile, so neither should `dra($e)` to my mind.
Nov 20 2022
parent Walter Bright <newshound2 digitalmars.com> writes:
On 11/20/2022 8:25 AM, IchorDev wrote:
 On Saturday, 19 November 2022 at 04:14:18 UTC, Walter Bright wrote:
 Is that a good thing? I'm not sure. This is also not addressed in the DIP.
Well `dra(E.e);` doesn't compile, so neither should `dra($e)` to my mind.
Ok, but that needs to be in the DIP!
Nov 20 2022
prev sibling next sibling parent reply Walter Bright <newshound2 digitalmars.com> writes:
The contextual inference only takes place in certain contexts. Perhaps we can 
run with that idea. Let's take case statements:

   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;
         /*...*/
     }
   }

and recognize that the SwitchExpression is of type WordLetterOfTheDay. 
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.

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

     S myS;
     myS.one = c; // myB.one = A.c
     myS.two = d; // myB.two = A.d
   }

To Return statements:

   enum A{ a,b,c,d }

   A myFn(){
     return c; //returns A.c
   }

   auto myBrokenFn(){
     return c; // error, c is undefined
   }

Argument lists:

   Only works if there are no overloads.

Array literals:

   enum A{ a,b,c,d }

   // (A)
   A[4] x = [a, b, c, d];
   // (B)
   auto y = [A.a, b, c, d]; // error, b is undefined
   auto z = [A.c, 64, b, b]; // error, b is undefined

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.

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
Nov 19 2022
next sibling parent rikki cattermole <rikki cattermole.co.nz> writes:
I like this design.
Nov 19 2022
prev sibling next sibling parent reply Adam D Ruppe <destructionator gmail.com> writes:
On Saturday, 19 November 2022 at 08:49:31 UTC, Walter Bright 
wrote:
 The contextual inference only takes place in certain contexts. 
 Perhaps we can run with that idea.
Would this generalize to struct construction like i mentioned here: https://forum.dlang.org/post/bievvzpabbxddogbmpgu forum.dlang.org If you can do an implicit with, you can also do an implicit alias of the with subject. And once you have implicit alias you can construct a struct which adds to the value significantly. Actually, I do wish `with` in general had a way to refer back to the subject of it. Maybe we could add something there then it'd magically apply to the implicit with too.
Nov 19 2022
parent reply Paul Backus <snarwin gmail.com> writes:
On Saturday, 19 November 2022 at 12:57:33 UTC, Adam D Ruppe wrote:
 Actually, I do wish `with` in general had a way to refer back 
 to the subject of it. Maybe we could add something there then 
 it'd magically apply to the implicit with too.
Maybe something like this for symbols: with (alias me = SomeReallyLongName) And this for expressions: with (auto me = some(complex, ex + pression)) Can be implemented by lowering to a normal block scope: { alias me = SomeReallyLongName; with (me) { // ... } }
Nov 19 2022
parent max haughton <maxhaton gmail.com> writes:
On Saturday, 19 November 2022 at 14:22:16 UTC, Paul Backus wrote:
 On Saturday, 19 November 2022 at 12:57:33 UTC, Adam D Ruppe 
 wrote:
 Actually, I do wish `with` in general had a way to refer back 
 to the subject of it. Maybe we could add something there then 
 it'd magically apply to the implicit with too.
Maybe something like this for symbols: with (alias me = SomeReallyLongName) And this for expressions: with (auto me = some(complex, ex + pression)) Can be implemented by lowering to a normal block scope: { alias me = SomeReallyLongName; with (me) { // ... } }
This + trailing with (a la `where`)
Nov 19 2022
prev sibling next sibling parent reply H. S. Teoh <hsteoh qfbox.info> writes:
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.
Nov 19 2022
parent Walter Bright <newshound2 digitalmars.com> writes:
On 11/19/2022 10:26 AM, H. S. Teoh wrote:
 Implicitly enclose the switch body with a `with (WordLetterOfTheDay)`
 resulting in:
Upon more reflection, the implicit `with` should only enclose the case expression, not the other statements in the switch body.
 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`.
Yes, should work the same as other initializations.
Nov 19 2022
prev sibling next sibling parent bachmeier <no spam.net> writes:
On Saturday, 19 November 2022 at 08:49:31 UTC, Walter Bright 
wrote:

 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
Looks much better to me. The number one reason for me is that it does not add tons of complexity/readability issues for new users.
Nov 19 2022
prev sibling next sibling parent reply zjh <fqbqrr 163.com> writes:
On Saturday, 19 November 2022 at 08:49:31 UTC, Walter Bright 
wrote:
 

 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
Can I open `one or more` 'enum' namespaces for a function, because sometimes, enum values are continuous,and you do not need `'switch'` statements. At this time, I still want to omit `'enum'` names' to use the `values`. Similarly, can we also open the 'namespace' of `one or more` classes or structs for a function. In this way, just like a `'free functions'`, you can directly use the 'static' function in the 'class/struct'. How about this?
Nov 19 2022
next sibling parent reply zjh <fqbqrr 163.com> writes:
On Sunday, 20 November 2022 at 01:07:14 UTC, zjh wrote:
 In this way, just like a `'free functions'`, you can directly 
 use the 'static' function in the 'class/struct'.

 How about this?
For a specific function, you only need to give the `syntax` for opening a specific namespace such as `'enum/struct/class'`etc. The `existing syntax/tools` will not be broken or not much damage.
Nov 19 2022
next sibling parent zjh <fqbqrr 163.com> writes:
On Sunday, 20 November 2022 at 01:11:49 UTC, zjh wrote:

 For a specific function, you only need to give the `syntax` for 
 opening a specific namespace such as `'enum/struct/class'`etc. 
 The `existing syntax/tools` will not be broken or not much 
 damage.
`With` is not as good as `using namespace std` in `C++`, because `with` is for a statement, while `using`can be for a `scope`. In this `scope/function`, you can omit the prefix of `struct/class/enum/...`.
Nov 19 2022
prev sibling parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 11/19/2022 5:11 PM, zjh wrote:
 For a specific function, you only need to give the `syntax` for opening a 
 specific namespace such as `'enum/struct/class'`etc. The `existing
syntax/tools` 
 will not be broken or not much damage.
https://dlang.org/spec/statement.html#with-statement In action: https://github.com/dlang/dmd/blob/master/compiler/src/dmd/tokens.d#L607
Nov 19 2022
parent zjh <fqbqrr 163.com> writes:
On Sunday, 20 November 2022 at 02:54:15 UTC, Walter Bright wrote:
 https://dlang.org/spec/statement.html#with-statement
 ...
I don't want `parentheses`. They have `indent` and `restriction`, which can be avoided. In my opinion, it is completely possible to open the `namespace` of `struct/class/enum` in the`function scope`, and the damage is not too much. Is the following OK?: ```d with Aenum,Bclass,Cstruct; ...directly using A,B,C in the whole function scope... ```
Nov 19 2022
prev sibling parent reply "H. S. Teoh" <hsteoh qfbox.info> writes:
On Sun, Nov 20, 2022 at 01:07:14AM +0000, zjh via Digitalmars-d wrote:
[...]
 Can I open `one or more` 'enum' namespaces for a function, because
 sometimes, enum values are continuous,and you do not need `'switch'`
 statements. At this time, I still want to omit `'enum'` names' to use
 the `values`.
 
 Similarly, can we also open the 'namespace' of `one or more` classes
 or structs for a function.

 In this way, just like a `'free functions'`, you can directly use the
 'static' function in the 'class/struct'.
 
 How about this?
This is exactly what `with` is designed for: enum MyLongEnum { LongValue, AnotherLongValue, YetAnotherLongValue } auto myFunc(Args...)(Args args) { with (MyLongEnum) { auto e = LongValue; ... // etc. } } Currently, `with` supports only one identifier; this could be enhanced to allow multiple identifiers so that you don't need to have 3-4 nested blocks just to have 3-4 implicit identifiers: enum MyLongEnum { ... } class MyClass { ... } struct MyStruct { ... } with (MyLongEnum, MyClass, MyStruct) { ... // use members of all 3 without needing to spell them out every time } T -- Long, long ago, the ancient Chinese invented a device that lets them see through walls. It was called the "window".
Nov 19 2022
parent reply zjh <fqbqrr 163.com> writes:
On Sunday, 20 November 2022 at 01:26:25 UTC, H. S. Teoh wrote:

 Currently, `with` supports only one identifier; this could be 
 enhanced to allow multiple identifiers so that you don't need 
 to have 3-4 nested blocks just to have 3-4 implicit identifiers:

 	enum MyLongEnum { ... }
 	class MyClass { ... }
 	struct MyStruct { ... }
 	with (MyLongEnum, MyClass, MyStruct) {
 		... // use members of all 3 without needing to spell them out 
 every time
 	}
It's a little different. I don't want to wrap it with a `{}`. I hope that the entire `function scope`can be used directly without adding a `prefix`. In my opinion, this is simpler,because most of the time `enum` are continuous. I can put `enumerater handler` functions into a `vector(or array)(C++)`, but still add `prefix`, which is a bit troublesome. It is very convenient if you do not add a prefix to the entire `function scope`. For example: ```d enum longName{A,B,C}; struct longName2{ static int g(){ ... } }; void f(){ using longName; using gg=function<int(int)>;//C++ gg[] fl;//gg fl[A],fl[B]... ...directly using A,B,C like this...; } void k(){ using longName2;//struct/class ...directly using static g... } ```
Nov 19 2022
parent reply zjh <fqbqrr 163.com> writes:
On Sunday, 20 November 2022 at 02:24:25 UTC, zjh wrote:

 ...
You only need to open the `namespace` of the `enum/struct/class` you need in the ` specific function`. That is, when you cannot find the `name/symbol`, find the `namespace` opened by the user in the function. I think it should be `easy` for `compiler writers`.
Nov 19 2022
parent zjh <fqbqrr 163.com> writes:
On Sunday, 20 November 2022 at 02:30:17 UTC, zjh wrote:

 You only need to open the `namespace` of the 
 `enum/struct/class` you need in the ` specific function`.
The `syntax` can be similar to: ```d using Aenum,Bclass,Cstruct; ``` You don't need `brackets`.
Nov 19 2022
prev sibling parent reply IchorDev <zxinsworld gmail.com> writes:
On Saturday, 19 November 2022 at 08:49:31 UTC, Walter Bright 
wrote:
 Advantages of this scheme:

 1. doesn't need the special `$` which people don't seem to 
 like, and using `.` conflicts with existing use
I'm up for changing it to something else, like I've said. It's just that I can't think of anything better except maybe `#member `:member` would be cool but it reminds me of C++ and would be a nightmare in so many cases. `%member` is alright but it looks like an operator. What about `->member`... actually nevermind I hate it. `\member`???
 3. seems to have a natural feel to it
I have mixed feelings about this. It's *very* hard to intuitively read that it's an enum member when it's written without any kind of affix at all, and it can't even work with overloaded functions. With some changes, I'd consider it.
Nov 20 2022
next sibling parent Walter Bright <newshound2 digitalmars.com> writes:
On 11/20/2022 8:29 AM, IchorDev wrote:
 On Saturday, 19 November 2022 at 08:49:31 UTC, Walter Bright wrote:
 Advantages of this scheme:

 1. doesn't need the special `$` which people don't seem to like, and using `.` 
 conflicts with existing use
I'm up for changing it to something else, like I've said. It's just that I can't think of anything better except maybe `#member right? `:member` would be cool but it reminds me of C++ and would be a nightmare in so many cases. `%member` is alright but it looks like an operator. What about `->member`... actually nevermind I hate it. `\member`???
So far, I haven't thought of a good syntax for it, either. That's what led me to think "what if we don't need the prefix at all".
 3. seems to have a natural feel to it
I have mixed feelings about this. It's *very* hard to intuitively read that it's an enum member when it's written without any kind of affix at all,
There is precedent for it. Fields in non-static member functions do not need a `this.` prefix, as there's an implicit `with(this)` for the function.
 and it can't even work with overloaded functions.
Overloaded functions are necessary, but I've often thought they are overused. But as I've mentioned in several comments here, the inferred enums lead to awkward problems for overload resolution - not just for the compiler, but for the user trying to figure out which overload is a better match. C++ overloading is so complex that basically nobody understands it - how people figure out which is matched is by trial and error, not understanding. While we could come up with arbitrary rules to resolve this, I suspect it is not worth it.
 With some changes, I'd consider it.
Good! This discussion thread is very productive.
Nov 20 2022
prev sibling parent reply TheGag96 <thegag96 gmail.com> writes:
On Sunday, 20 November 2022 at 16:29:46 UTC, IchorDev wrote:
 I'm up for changing it to something else, like I've said. It's 
 just that I can't think of anything better except maybe 
 `#member
Could you elaborate on this? I thought I was going nuts until I to be the most agreed-upon alternative to `.`. If we were to makes a lot of sense... It calls back to the "num(ber)" part of
Nov 21 2022
parent reply Paul Backus <snarwin gmail.com> writes:
On Monday, 21 November 2022 at 15:45:59 UTC, TheGag96 wrote:
 On Sunday, 20 November 2022 at 16:29:46 UTC, IchorDev wrote:
 I'm up for changing it to something else, like I've said. It's 
 just that I can't think of anything better except maybe 
 `#member
Could you elaborate on this? I thought I was going nuts until I seemed to be the most agreed-upon alternative to `.`. If we kind of makes a lot of sense... It calls back to the "num(ber)"
sequence][1]. [1]: https://dlang.org/spec/lex.html#special-token-sequence
Nov 21 2022
parent TheGag96 <thegag96 gmail.com> writes:
On Monday, 21 November 2022 at 15:48:55 UTC, Paul Backus wrote:

 sequence][1].

 [1]: https://dlang.org/spec/lex.html#special-token-sequence
Wow. Only barely recalled ever seeing this feature from the depths of my memory. Thanks, lol. That's a shame... I like this proposed feature, but I don't know if I like the `$` syntax. At first blush it's a bit ugly looking and might clash visually somewhat with the `$` operator. The `enum.` suggestion isn't super bad but it's a bit wordy. Regardless I think it would be super nice to have parity with other languages with regard to less wordy enum usage.
Nov 21 2022
prev sibling next sibling parent reply Vladimir Panteleev <thecybershadow.lists gmail.com> writes:
On Friday, 18 November 2022 at 15:37:31 UTC, Mike Parker wrote:


 This is the discussion thread for the first round of Community 
 Review of DIP 1044, "Enum Type Inference":
[half feedback, half random brainstorming, so posting here to be safe] I would like to suggest the following changes for consideration: - Replace the `$ Identifier` syntax with `: Identifier`, to match other languages like Ruby and Lisp. - The `: Identifier` syntax creates a value of a dynamic pseudo-type (a bit like `typeof(null)`). - The type's name is `typeof(:Identifier)`. - The type has size 0 and holds a single value. - The type is implicitly convertible to any enum type which has a member with the same name as `Identifier`. I think this is a more precise and immediately implementable definition of the mechanics. Not sure if a good thing or not, but this will also allow using `:keyword`s stand-alone, like in Ruby/Lisp in a congruent manner. For the purposes at hand (enum type inference), it will also allow passing through the short-hand identifier to templated and `auto` functions. It will not allow ```d myFn($a + $a); // passes A.b ``` to work, but I'm not sure that would be implementable anyway in a reasonable manner and provide justifiable value. I think the remaining examples in the DIP will continue to work. On another point, since the DIP mentions the `with` approach, I'll mention that the workaround I've been using is to declare a short local alias for the enum type. At the top level (e.g. for variable/constant initializers), it can be done by wrapping the value in a CTFE function: https://gist.github.com/CyberShadow/54ca7a0fa594c2272cabf8677ff6e42f#file-game-d-L150
Nov 19 2022
parent Timon Gehr <timon.gehr gmx.ch> writes:
On 19.11.22 18:29, Vladimir Panteleev wrote:
 
 I would like to suggest the following changes for consideration:
 
 - Replace the `$ Identifier` syntax with `: Identifier`, to match other 
 languages like Ruby and Lisp.
 
 - The `: Identifier` syntax creates a value of a dynamic pseudo-type (a 
 bit like `typeof(null)`).
 
    - The type's name is `typeof(:Identifier)`.
 
    - The type has size 0 and holds a single value.
 
    - The type is implicitly convertible to any enum type which has a 
 member with the same name as `Identifier`.
 
 I think this is a more precise and immediately implementable definition 
 of the mechanics. Not sure if a good thing or not, but this will also 
 allow using `:keyword`s stand-alone, like in Ruby/Lisp in a congruent 
 manner. For the purposes at hand (enum type inference), it will also 
 allow passing through the short-hand identifier to templated and `auto` 
 functions.
I think this makes some sense. (I especially prefer the syntax and the standalone symbol approach). With this proposal, we'd have to think about the matching level for function overloads (delegates match precisely even if they require inference), as with your approach one can overload an enum argument against a typeof(:identifier). Probably exact match would be better than match with implicit conversion, but idk if it is worth changing/bending the overloading rules over this.
Nov 20 2022
prev sibling next sibling parent reply monkyyy <crazymonkyyy gmail.com> writes:
On Friday, 18 November 2022 at 15:37:31 UTC, Mike Parker wrote:

The discord is talking allot about alt characters %, €, 🃏, ?, . With 🃏 being the best suggestion
Nov 19 2022
parent reply cc <cc nevernet.com> writes:
On Saturday, 19 November 2022 at 17:47:16 UTC, monkyyy wrote:
 The discord is talking allot about alt characters

 %, €, 🃏, ?, .

 With 🃏 being the best suggestion
Would it be categorically insane to try to implement this with no punctuation identifier at all?
Nov 19 2022
parent Walter Bright <newshound2 digitalmars.com> writes:
On 11/19/2022 9:56 AM, cc wrote:
 Would it be categorically insane to try to implement this with no punctuation 
 identifier at all?
Insane: https://www.digitalmars.com/d/archives/digitalmars/D/Discussion_Thread_DIP_1044--Enum_Type_Inference--Community_Review_365880.html#N365938
Nov 19 2022
prev sibling next sibling parent reply deadalnix <deadalnix gmail.com> writes:
On Friday, 18 November 2022 at 15:37:31 UTC, Mike Parker wrote:


 This is the discussion thread for the first round of Community 
 Review of DIP 1044, "Enum Type Inference":

 https://github.com/dlang/DIPs/blob/e2ca557ab9d3e60305a37da0d5b58299e0a9de0e/DIPs/DIP1044.md

 The review period will **end at 11:59 PM ET on December 3**, or 
 when I make a post declaring it complete. Discussion in this 
 thread may continue beyond that point.

 Here in the discussion thread, you are free to discuss anything 
 and everything related to the DIP. Express your support or 
 opposition, debate alternatives, argue the merits, etc.

 However, if you have any specific feedback on how to improve 
 the proposal itself, then please post it in the Feedback 
 Thread. The Feedback Thread will be the source for the review 
 summary that I will write at the end of this review round. I 
 will post a link to that thread immediately following this 
 post. Just be sure to read and understand the Reviewer 
 Guidelines before posting there:

 https://github.com/dlang/DIPs/blob/master/docs/guidelines-reviewers.md

 And my blog post on the difference between the Discussion and 
 Feedback threads:

 https://dlang.org/blog/2020/01/26/dip-reviews-discussion-vs-feedback/

 Please stay on topic here. I will delete posts that are 
 completely off-topic.
I have very simple feedback. STOP CHANGING THE GOD DAMN SYNTAX! STOP, STOP, STOP, and if you still have some doubt, STOP! Every time, it breaks a ton of tools. It's not worth it. If typing the name of the enum is too long, then just use `with` or `alias E = MyEnumNameThatIsTooLongAndAnoyingToType;`. These changes do not solve any actual problem. They just break tools. STOP IT!
Nov 19 2022
next sibling parent reply ryuukk_ <ryuukk.dev gmail.com> writes:
On Sunday, 20 November 2022 at 01:00:58 UTC, deadalnix wrote:
 On Friday, 18 November 2022 at 15:37:31 UTC, Mike Parker wrote:


 This is the discussion thread for the first round of Community 
 Review of DIP 1044, "Enum Type Inference":

 https://github.com/dlang/DIPs/blob/e2ca557ab9d3e60305a37da0d5b58299e0a9de0e/DIPs/DIP1044.md

 The review period will **end at 11:59 PM ET on December 3**, 
 or when I make a post declaring it complete. Discussion in 
 this thread may continue beyond that point.

 Here in the discussion thread, you are free to discuss 
 anything and everything related to the DIP. Express your 
 support or opposition, debate alternatives, argue the merits, 
 etc.

 However, if you have any specific feedback on how to improve 
 the proposal itself, then please post it in the Feedback 
 Thread. The Feedback Thread will be the source for the review 
 summary that I will write at the end of this review round. I 
 will post a link to that thread immediately following this 
 post. Just be sure to read and understand the Reviewer 
 Guidelines before posting there:

 https://github.com/dlang/DIPs/blob/master/docs/guidelines-reviewers.md

 And my blog post on the difference between the Discussion and 
 Feedback threads:

 https://dlang.org/blog/2020/01/26/dip-reviews-discussion-vs-feedback/

 Please stay on topic here. I will delete posts that are 
 completely off-topic.
I have very simple feedback. STOP CHANGING THE GOD DAMN SYNTAX! STOP, STOP, STOP, and if you still have some doubt, STOP! Every time, it breaks a ton of tools. It's not worth it. If typing the name of the enum is too long, then just use `with` or `alias E = MyEnumNameThatIsTooLongAndAnoyingToType;`. These changes do not solve any actual problem. They just break tools. STOP IT!
Relax, it's just a discussion As for tooling i agree, we should not break tooling, hence why i advocate for synchronizing tooling updates with language updates: https://forum.dlang.org/thread/bjurxmbmdtcxblgcswch forum.dlang.org As for the feature, having to `alias` is the reason why i advocate for that feature, we should not have to alias things and add useless cognitive load to read obvious lines This features doesn't solve your problems, but it personally solve mines If tooling is synchronized with the feature, do you still have an objection for this feature? ```D MySuperDuperLongEnum stuff = MySuperDuperLongEnum.VALUE_A; ``` Why should i use an alias here for this simple variable? don't you see it as an improvement? ```D MySuperDuperLongEnum stuff = .VALUE_A; ``` why should i use an alias here? ```D ctx.network_state = State.NetworkState.CONNECTED; // vs ctx.network_state = .CONNECTED; ```
Nov 19 2022
parent reply "H. S. Teoh" <hsteoh qfbox.info> writes:
On Sun, Nov 20, 2022 at 03:31:44AM +0000, ryuukk_ via Digitalmars-d wrote:
[...]
 ```D
 MySuperDuperLongEnum stuff = MySuperDuperLongEnum.VALUE_A;
 ```
Why not just write: auto stuff = MySuperDuperLongEnum.VALUE_A; ? No repetition necessary. [...]
 why should i use an alias here?
 ```D
 ctx.network_state = State.NetworkState.CONNECTED;
 
 // vs
 
 ctx.network_state = .CONNECTED;
 ```
Walter's proposal of implicit `with` would solve this case. T -- "You are a very disagreeable person." "NO."
Nov 20 2022
parent ryuukk_ <ryuukk.dev gmail.com> writes:
On Sunday, 20 November 2022 at 18:03:04 UTC, H. S. Teoh wrote:
 On Sun, Nov 20, 2022 at 03:31:44AM +0000, ryuukk_ via 
 Digitalmars-d wrote: [...]
 ```D
 MySuperDuperLongEnum stuff = MySuperDuperLongEnum.VALUE_A;
 ```
Why not just write: auto stuff = MySuperDuperLongEnum.VALUE_A; ? No repetition necessary.
```D struct Data { MySuperDuperLongEnum flags; } Data data = { flags: .VALUE_A | .VALUE_B }; ```
 [...]
 why should i use an alias here?
 ```D
 ctx.network_state = State.NetworkState.CONNECTED;
 
 // vs
 
 ctx.network_state = .CONNECTED;
 ```
Walter's proposal of implicit `with` would solve this case. T
Implicit is indeed a good idea, Adam's idea is also interesting
Nov 20 2022
prev sibling next sibling parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 20.11.22 02:00, deadalnix wrote:
 
 I have very simple feedback.
 
 STOP CHANGING THE GOD DAMN SYNTAX!
 STOP, STOP, STOP, and if you still have some doubt, STOP!
 
 Every time, it breaks a ton of tools.
 
 It's not worth it.
 ...
It's not worth freezing the language over temporary tool breakage. Just don't update the compiler until the tools have caught up.
 If typing the name of the enum is too long, then just use `with` or 
 `alias E = MyEnumNameThatIsTooLongAndAnoyingToType;`.
 ...
Right, if typing the name of the enum is too long, then just type the name of the enum. x)
 These changes do not solve any actual problem.
Well, they do.
 They just break tools.
 
 STOP IT!
There has to be a better way.
Nov 20 2022
next sibling parent Dukc <ajieskola gmail.com> writes:
On Sunday, 20 November 2022 at 09:39:11 UTC, Timon Gehr wrote:
 On 20.11.22 02:00, deadalnix wrote:
 
 I have very simple feedback.
 
 STOP CHANGING THE GOD DAMN SYNTAX!
 STOP, STOP, STOP, and if you still have some doubt, STOP!
 
 Every time, it breaks a ton of tools.
 
 It's not worth it.
 ...
It's not worth freezing the language over temporary tool breakage. Just don't update the compiler until the tools have caught up.
I agree. Besides, the change at syntax phase is as simple as it gets: dollar with letters/underscore following it must be considered a symbol name. All other changes are at semantic level a syntactic tool does not have to worry about.
Nov 20 2022
prev sibling parent reply deadalnix <deadalnix gmail.com> writes:
On Sunday, 20 November 2022 at 09:39:11 UTC, Timon Gehr wrote:
 It's not worth freezing the language over temporary tool 
 breakage. Just don't update the compiler until the tools have 
 caught up.
Here is where you are wrong: it's not temporary breakage, it's permanent, but this whole circus happens every few of months. We can argue all day long, but the proof is in the pudding: D tooling is abysmal and kinda broken pretty much everywhere. It's not hard to figure out why: people implement D support at some point, and then changes accumulate and support kinda work, kinda not.
 There has to be a better way.
There is. Bundle the breakage, and release them all at once every couple of years. Every single language out there does that, there is a reason for it.
Nov 20 2022
next sibling parent IchorDev <zxinsworld gmail.com> writes:
On Sunday, 20 November 2022 at 15:28:37 UTC, deadalnix wrote:
 There is. Bundle the breakage, and release them all at once 
 every couple of years. Every single language out there does 
 that, there is a reason for it.
Sorry but haha... Python exists. They broke heaps of code with an unannounced security patch to "fix" the bigints being ... you'll never guess this one... ... ... ... ... too big.
Nov 20 2022
prev sibling parent Timon Gehr <timon.gehr gmx.ch> writes:
On 20.11.22 16:28, deadalnix wrote:
 On Sunday, 20 November 2022 at 09:39:11 UTC, Timon Gehr wrote:
 It's not worth freezing the language over temporary tool breakage. 
 Just don't update the compiler until the tools have caught up.
Here is where you are wrong: it's not temporary breakage, it's permanent,
I am pretty sure tools can be updated.
 but this whole circus happens every few of months.
 
 We can argue all day long,
I'd rather not, but I do think it's a bit weird that you are arguing against new language features in general, in a DIP discussion thread about one specific feature, on the grounds that you actually just disagree with the release schedule.
 but the proof is in the pudding: D tooling is 
 abysmal and kinda broken pretty much everywhere. It's not hard to figure 
 out why:
Sure, the reason is lack of resources and the fact that tooling is not viewed as a priority because it is not already a strength.
 people implement D support at some point, and then changes 
 accumulate and support kinda work, kinda not.
 ...
There is no such thing as "D" support. Versioning exists.
 There has to be a better way.
There is. Bundle the breakage,
Which D is doing. Nobody is expected to build their programs off DMD master.
 and release them all at once every couple of years.
I.e., the difference is that they have LTS versions. The solution you proposed (and I had an issue with) is to stop evolving the language.
 Every single language out there
That seems a little bit exaggerated.
 does that, there is a reason for it.
The reason is that they have more resources.
Nov 20 2022
prev sibling next sibling parent reply Johan <j j.nl> writes:
On Sunday, 20 November 2022 at 01:00:58 UTC, deadalnix wrote:
 On Friday, 18 November 2022 at 15:37:31 UTC, Mike Parker wrote:


 This is the discussion thread for the first round of Community 
 Review of DIP 1044, "Enum Type Inference":

 https://github.com/dlang/DIPs/blob/e2ca557ab9d3e60305a37da0d5b58299e0a9de0e/DIPs/DIP1044.md
I have very simple feedback. STOP CHANGING THE GOD DAMN SYNTAX! STOP, STOP, STOP, and if you still have some doubt, STOP! Every time, it breaks a ton of tools. It's not worth it. If typing the name of the enum is too long, then just use `with` or `alias E = MyEnumNameThatIsTooLongAndAnoyingToType;`. These changes do not solve any actual problem. They just break tools.
I quite strongly agree. The DIP does not show any real improvements. The rationale mentions "few drawbacks" but then does not mention those actual drawbacks, so people can judge whether they are few or not. The DIP show this example as an improvement: ``` myObj.myFn($medium, $square, $undefined); ``` Is the height medium?, the location the town square?, the shape undefined? This is the "worse" version: ``` myObj.myFn(Size.medium, Shape.square, State.undefined); ``` Code will be _read_ much more often than it is _written_. Please give a real world example where really the enum name is so long and tedious that _reading_ it is worse than without (and where `with` does not solve the problem). Besides tooling, also take into account someone relatively unfamiliar with D, stumbling upon a `$`. (now what the heck is this gratuitous obfuscation?) -Johan
Nov 20 2022
next sibling parent reply ryuukk_ <ryuukk.dev gmail.com> writes:
On Sunday, 20 November 2022 at 16:14:41 UTC, Johan wrote:
 On Sunday, 20 November 2022 at 01:00:58 UTC, deadalnix wrote:
 On Friday, 18 November 2022 at 15:37:31 UTC, Mike Parker wrote:


 This is the discussion thread for the first round of 
 Community Review of DIP 1044, "Enum Type Inference":

 https://github.com/dlang/DIPs/blob/e2ca557ab9d3e60305a37da0d5b58299e0a9de0e/DIPs/DIP1044.md
I have very simple feedback. STOP CHANGING THE GOD DAMN SYNTAX! STOP, STOP, STOP, and if you still have some doubt, STOP! Every time, it breaks a ton of tools. It's not worth it. If typing the name of the enum is too long, then just use `with` or `alias E = MyEnumNameThatIsTooLongAndAnoyingToType;`. These changes do not solve any actual problem. They just break tools.
I quite strongly agree. The DIP does not show any real improvements. The rationale mentions "few drawbacks" but then does not mention those actual drawbacks, so people can judge whether they are few or not. The DIP show this example as an improvement: ``` myObj.myFn($medium, $square, $undefined); ``` Is the height medium?, the location the town square?, the shape undefined? This is the "worse" version: ``` myObj.myFn(Size.medium, Shape.square, State.undefined); ``` Code will be _read_ much more often than it is _written_. Please give a real world example where really the enum name is so long and tedious that _reading_ it is worse than without (and where `with` does not solve the problem). Besides tooling, also take into account someone relatively unfamiliar with D, stumbling upon a `$`. (now what the heck is this gratuitous obfuscation?) -Johan
D has good type system first off, name properly your functions/types/variables then about the problem you are raising: ```D attack_enemy(1, 10, 5); void attack_enemy(int id, int damage, float modifier) {} ``` How do you know the last parameter is a float? to quote you: "now what the heck is this gratuitous obfuscation" Now another example: ```D int currhp = player.hp; ``` is hp a variable? or is it a function that's gonna do some logic?, if that's a function, will it throw? will it, is it thread safe? to quote you again: "now what the heck is this gratuitous obfuscation" The DIP doesn't enforce you to omit the type name, it gives you the ability to omit it when the context is clear, let's you setup a long and verbose name without sacrificing readability of your code when you use it ```D NetworkState network_state = State.NetworkState.CONNECTED; ``` to quote you again: "now what the heck is this gratuitous obfuscation" the repetition adds useless cognitive load, makes the line harder to read, and makes me want to give up proper type scoping (putting enum under the struct scope), and it encourages me to use shorter enum name, wich gives you poor APIs as a result `TOK` enum in DMD codebase instead of `SymbolTokenType` D is not dynamic typed, we should leverage the type system to encourage lean code without sacrificing readable APIs
Nov 20 2022
parent reply Johan <j j.nl> writes:
On Sunday, 20 November 2022 at 16:30:46 UTC, ryuukk_ wrote:
 On Sunday, 20 November 2022 at 16:14:41 UTC, Johan wrote:
 On Sunday, 20 November 2022 at 01:00:58 UTC, deadalnix wrote:
 On Friday, 18 November 2022 at 15:37:31 UTC, Mike Parker 
 wrote:


 This is the discussion thread for the first round of 
 Community Review of DIP 1044, "Enum Type Inference":

 https://github.com/dlang/DIPs/blob/e2ca557ab9d3e60305a37da0d5b58299e0a9de0e/DIPs/DIP1044.md
I have very simple feedback. STOP CHANGING THE GOD DAMN SYNTAX! STOP, STOP, STOP, and if you still have some doubt, STOP! Every time, it breaks a ton of tools. It's not worth it. If typing the name of the enum is too long, then just use `with` or `alias E = MyEnumNameThatIsTooLongAndAnoyingToType;`. These changes do not solve any actual problem. They just break tools.
I quite strongly agree. The DIP does not show any real improvements. The rationale mentions "few drawbacks" but then does not mention those actual drawbacks, so people can judge whether they are few or not. The DIP show this example as an improvement: ``` myObj.myFn($medium, $square, $undefined); ``` Is the height medium?, the location the town square?, the shape undefined? This is the "worse" version: ``` myObj.myFn(Size.medium, Shape.square, State.undefined); ``` Code will be _read_ much more often than it is _written_. Please give a real world example where really the enum name is so long and tedious that _reading_ it is worse than without (and where `with` does not solve the problem). Besides tooling, also take into account someone relatively unfamiliar with D, stumbling upon a `$`. (now what the heck is this gratuitous obfuscation?) -Johan
D has good type system
Irrelevant.
 first off, name properly your functions/types/variables
Irrelevant.
 then about the problem you are raising:
In your long email, you are not addressing at all how this DIP addresses any of the problems I am raising. Just mentioning more examples of code that are not fixed by this DIP.
 `TOK` enum in DMD codebase instead of `SymbolTokenType`
Thank you for this example. Search DMD codebase for `TOK`, and tell me how this DIP would matter for renaming `TOK` to `SymbolTokenType`: ``` dmd/compiler/src/dmd/cond.d: 195 { 196 auto tf = new TypeFunction(ParameterList(), null, LINK.default_, 0); 197: auto fd = new FuncLiteralDeclaration(loc, loc, tf, TOK.reserved, null); 198 fd.fbody = s; 199 auto fe = new FuncExp(loc, fd); ... 407 auto exps = new Expressions(length); 408 409: if (rangefe.op == TOK.foreach_) 410 { 411 foreach (i; 0 .. length) ``` ``` dmd/compiler/src/dmd/cparse.d: 112 while (1) 113 { 114: if (token.value == TOK.endOfFile) 115 { 116 addDefines(); // convert #define's to Dsymbols ``` This DIP is not needed. `TOK` can happily be renamed to `SymbolTokenType`. Let's not waste time on it. -Johan
Nov 20 2022
parent ryuukk_ <ryuukk.dev gmail.com> writes:
On Sunday, 20 November 2022 at 19:11:31 UTC, Johan wrote:
 On Sunday, 20 November 2022 at 16:30:46 UTC, ryuukk_ wrote:
 On Sunday, 20 November 2022 at 16:14:41 UTC, Johan wrote:
 On Sunday, 20 November 2022 at 01:00:58 UTC, deadalnix wrote:
 On Friday, 18 November 2022 at 15:37:31 UTC, Mike Parker 
 wrote:


 This is the discussion thread for the first round of 
 Community Review of DIP 1044, "Enum Type Inference":

 https://github.com/dlang/DIPs/blob/e2ca557ab9d3e60305a37da0d5b58299e0a9de0e/DIPs/DIP1044.md
I have very simple feedback. STOP CHANGING THE GOD DAMN SYNTAX! STOP, STOP, STOP, and if you still have some doubt, STOP! Every time, it breaks a ton of tools. It's not worth it. If typing the name of the enum is too long, then just use `with` or `alias E = MyEnumNameThatIsTooLongAndAnoyingToType;`. These changes do not solve any actual problem. They just break tools.
I quite strongly agree. The DIP does not show any real improvements. The rationale mentions "few drawbacks" but then does not mention those actual drawbacks, so people can judge whether they are few or not. The DIP show this example as an improvement: ``` myObj.myFn($medium, $square, $undefined); ``` Is the height medium?, the location the town square?, the shape undefined? This is the "worse" version: ``` myObj.myFn(Size.medium, Shape.square, State.undefined); ``` Code will be _read_ much more often than it is _written_. Please give a real world example where really the enum name is so long and tedious that _reading_ it is worse than without (and where `with` does not solve the problem). Besides tooling, also take into account someone relatively unfamiliar with D, stumbling upon a `$`. (now what the heck is this gratuitous obfuscation?) -Johan
D has good type system
Irrelevant.
It is relevant, care to bring more argumentation?
 first off, name properly your functions/types/variables
Irrelevant.
It is relevant, care to bring more argumentation?
 then about the problem you are raising:
In your long email, you are not addressing at all how this DIP addresses any of the problems I am raising. Just mentioning more examples of code that are not fixed by this DIP.
I'm unfortunately not qualified to answer every concerns and questions, i'm not a language developer or a compiler designer, i never wrote grammar stuff, i'm a mere language user, i can only share my experience writing code in my project So i am thankful for all of you who share your opinions too, there is lot to learn
 `TOK` enum in DMD codebase instead of `SymbolTokenType`
Thank you for this example. Search DMD codebase for `TOK`, and tell me how this DIP would matter for renaming `TOK` to `SymbolTokenType`: ``` dmd/compiler/src/dmd/cond.d: 195 { 196 auto tf = new TypeFunction(ParameterList(), null, LINK.default_, 0); 197: auto fd = new FuncLiteralDeclaration(loc, loc, tf, TOK.reserved, null); 198 fd.fbody = s; 199 auto fe = new FuncExp(loc, fd); ... 407 auto exps = new Expressions(length); 408 409: if (rangefe.op == TOK.foreach_) 410 { 411 foreach (i; 0 .. length) ``` ``` dmd/compiler/src/dmd/cparse.d: 112 while (1) 113 { 114: if (token.value == TOK.endOfFile) 115 { 116 addDefines(); // convert #define's to Dsymbols ``` This DIP is not needed. `TOK` can happily be renamed to `SymbolTokenType`. Let's not waste time on it. -Johan
I used TOK example because it was mentioned in this thread ```D if (token.value == TOK.endOfFile) ``` what's token.value????? you guessed that .value is the value of the TokenType? ```D if (token.token_type == .endOfFile) ``` I'd love to know what was the reasoning behind ``TOK`` naming, was it because it was too long? that would be my guess
Nov 20 2022
prev sibling parent Patrick Schluter <Patrick.Schluter bbox.fr> writes:
On Sunday, 20 November 2022 at 16:14:41 UTC, Johan wrote:

 These changes do not solve any actual problem. They just break 
 tools.
I quite strongly agree.
Me too.
 The DIP does not show any real improvements. The rationale 
 mentions "few drawbacks" but then does not mention those actual 
 drawbacks, so people can judge whether they are few or not.

 The DIP show this example as an improvement:
 ```
     myObj.myFn($medium, $square, $undefined);
 ```
 Is the height medium?, the location the town square?, the shape 
 undefined?
 This is the "worse" version:
 ```
     myObj.myFn(Size.medium, Shape.square, State.undefined);
 ```

 Code will be _read_ much more often than it is _written_.
 Please give a real world example where really the enum name is 
 so long and tedious that _reading_ it is worse than without 
 (and where `with` does not solve the problem).
Indeed. This DIP goes also in direct contradiction to the named parameter DIP, which strives to make the code more explicit, with naming the parameter. This thing would then require for readability to call like that: ``` myObj.myFn(Size: $medium, Shape: $square, State: $undefined); ```
 Besides tooling, also take into account someone relatively 
 unfamiliar with D, stumbling upon a `$`. (now what the heck is 
 this gratuitous obfuscation?)
Making D as "readable" as Perl. :-)
Nov 21 2022
prev sibling next sibling parent reply IchorDev <zxinsworld gmail.com> writes:
On Sunday, 20 November 2022 at 01:00:58 UTC, deadalnix wrote:
 STOP CHANGING THE GOD DAMN SYNTAX! STOP, STOP, STOP, and if you 
 still have some doubt, STOP! STOP IT!
 (etc. etc.)
Thank you for your hateful rant, but please actually read the DIP. `;P` I carefully wrote the DIP for ETI in order to avoid breaking or changing the behaviour of any existing code. That's why I settled on the `$member` syntax for the original draft.
Nov 20 2022
parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 20.11.22 17:31, IchorDev wrote:
 On Sunday, 20 November 2022 at 01:00:58 UTC, deadalnix wrote:
 STOP CHANGING THE GOD DAMN SYNTAX! STOP, STOP, STOP, and if you still 
 have some doubt, STOP! STOP IT!
 (etc. etc.)
Thank you for your hateful rant, but please actually read the DIP. `;P` I carefully wrote the DIP for ETI in order to avoid breaking or changing the behaviour of any existing code. That's why I settled on the `$member` syntax for the original draft.
His problem is that the compiler will be the first tool that can parse the new syntax and other tools will by default not work anymore on code that uses the new syntax.
Nov 20 2022
parent IchorDev <zxinsworld gmail.com> writes:
On Sunday, 20 November 2022 at 17:07:52 UTC, Timon Gehr wrote:
 His problem is that the compiler will be the first tool that 
 can parse the new syntax and other tools will by default not 
 work anymore on code that uses the new syntax.
I'll quote what I said on the server:
 [...] Languages update. D has always had regular breaking 
 changes for better or worse... that's just what it is. If they 
 don't like that... they should probably not be maintaining a 
 code formatter for [Dlang.]
Nov 20 2022
prev sibling parent Walter Bright <newshound2 digitalmars.com> writes:
On 11/19/2022 5:00 PM, deadalnix wrote:
 STOP CHANGING THE GOD DAMN SYNTAX!
 STOP, STOP, STOP, and if you still have some doubt, STOP!
You might like the Alternative Possibility in this thread.
Nov 20 2022
prev sibling next sibling parent Guillaume Piolat <first.last spam.org> writes:
On Friday, 18 November 2022 at 15:37:31 UTC, Mike Parker wrote:
 Here in the discussion thread, you are free to discuss anything 
 and everything related to the DIP. Express your support or 
 opposition, debate alternatives, argue the merits, etc.
Not very interested, also would prefer: - 1. more explicit syntax for global scope .symbol (anything really) Even in C++ ::symbol is not self-explanating. - deprecate .symbol - reuse .symbol for that purpose eventually
Nov 19 2022
prev sibling next sibling parent CM <celestialmachinist proton.me> writes:
On Friday, 18 November 2022 at 15:37:31 UTC, Mike Parker wrote:


 [...]
Putting aside the syntax, which is aesthetically displeasing to me, I don't see much utility over *alias* and *with* to justify this DIP's acceptance, and that's without considering the tooling argument. That said, Walter's "implicit with" looks neat.
Nov 20 2022
prev sibling next sibling parent reply bauss <jacobbauss gmail.com> writes:
On Friday, 18 November 2022 at 15:37:31 UTC, Mike Parker wrote:


 This is the discussion thread for the first round of Community 
 Review of DIP 1044, "Enum Type Inference":
Not a fun of it using $identifier to imply inference. I would much rather like .identifier. I know that is currently used for module scope, but it could have been changed to something like static interference instead, so it will default to module scope, but can look into other types like enum, static members of classes etc. Basically: ```d int a = 1; class B { static: int b = 2; } enum MyEnum { c = 3 } void main() { writeln(.a); writeln(.b); writeln(.c); } ``` Output: ``` 1 2 3 ``` Basically module scope has first priority, second enum, third static members. So an ambiguity error shouldn't happen if a module scoped variable is named the same as an enum member etc.
Nov 21 2022
parent bauss <jacobbauss gmail.com> writes:
On Monday, 21 November 2022 at 09:25:53 UTC, bauss wrote:
 Not a fun of it using $identifier to imply inference.
Typo: Meant fan
Nov 21 2022
prev sibling next sibling parent Basile.B <b2.temp gmx.com> writes:
On Friday, 18 November 2022 at 15:37:31 UTC, Mike Parker wrote:


 This is the discussion thread for the first round of Community 
 Review of DIP 1044, "Enum Type Inference":

 https://github.com/dlang/DIPs/blob/e2ca557ab9d3e60305a37da0d5b58299e0a9de0e/DIPs/DIP1044.md

 The review period will **end at 11:59 PM ET on December 3**, or 
 when I make a post declaring it complete. Discussion in this 
 thread may continue beyond that point.

 Here in the discussion thread, you are free to discuss anything 
 and everything related to the DIP. Express your support or 
 opposition, debate alternatives, argue the merits, etc.

 However, if you have any specific feedback on how to improve 
 the proposal itself, then please post it in the Feedback 
 Thread. The Feedback Thread will be the source for the review 
 summary that I will write at the end of this review round. I 
 will post a link to that thread immediately following this 
 post. Just be sure to read and understand the Reviewer 
 Guidelines before posting there:

 https://github.com/dlang/DIPs/blob/master/docs/guidelines-reviewers.md

 And my blog post on the difference between the Discussion and 
 Feedback threads:

 https://dlang.org/blog/2020/01/26/dip-reviews-discussion-vs-feedback/

 Please stay on topic here. I will delete posts that are 
 completely off-topic.
The EnumExpression shortucts the whole shadowing problem EnumExpression ::= "enum" "." Identifier So when that kind of expression is resolved, you just have to look at if there's an enum put in the current scope for that special inference case and if it contains the right member. That would look like this EnumType myBitset = enum.flag1 | enum.flag3 So you push `EnumType` in the scope used to solve the assign expression. you see ?
Nov 21 2022
prev sibling next sibling parent monkyyy <crazymonkyyy gmail.com> writes:
On Friday, 18 November 2022 at 15:37:31 UTC, Mike Parker wrote:

The issue is that c bindings tend to be verbose; so what if importc(with a flag?) flattened enums into global scope, mimicking c given `enum foo{a,b}` in a .c; is traslated to `enum a=0; enum b=1` In the internal ast; so`foo bar=a` works in a .d
Nov 21 2022
prev sibling next sibling parent reply IchorDev <zxinsworld gmail.com> writes:
If you'd like to vote about what ETI syntax you'd prefer, I've 
opened a poll to keep track of how many people like which syntax.
The options I've listed are limited to ones that don't break 
compatibility with existing code. If you'd like an option added, 
let me know.
https://strawpoll.com/polls/PKglzqaGJyp
Nov 21 2022
next sibling parent monkyyy <crazymonkyyy gmail.com> writes:
On Monday, 21 November 2022 at 16:23:51 UTC, IchorDev wrote:
 If you'd like to vote about what ETI syntax you'd prefer, I've 
 opened a poll to keep track of how many people like which 
 syntax.
 The options I've listed are limited to ones that don't break 
 compatibility with existing code. If you'd like an option 
 added, let me know.
 https://strawpoll.com/polls/PKglzqaGJyp
```d enum bar{foo,foobar} bar b=🃏.foo; ```
Nov 21 2022
prev sibling next sibling parent reply Guillaume Piolat <first.last spam.org> writes:
On Monday, 21 November 2022 at 16:23:51 UTC, IchorDev wrote:
 If you'd like to vote about what ETI syntax you'd prefer, I've 
 opened a poll to keep track of how many people like which 
 syntax.
 The options I've listed are limited to ones that don't break 
 compatibility with existing code. If you'd like an option 
 added, let me know.
 https://strawpoll.com/polls/PKglzqaGJyp
There is no .member syntax in your poll (which implies deprecating existing one)
Nov 21 2022
next sibling parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 21.11.22 21:12, Guillaume Piolat wrote:
 On Monday, 21 November 2022 at 16:23:51 UTC, IchorDev wrote:
 If you'd like to vote about what ETI syntax you'd prefer, I've opened 
 a poll to keep track of how many people like which syntax.
 The options I've listed are limited to ones that don't break 
 compatibility with existing code. If you'd like an option added, let 
 me know.
 https://strawpoll.com/polls/PKglzqaGJyp
There is no .member syntax in your poll (which implies deprecating existing one)
_.member is also missing.
Nov 21 2022
parent reply IchorDev <zxinsworld gmail.com> writes:
On Tuesday, 22 November 2022 at 01:43:25 UTC, Timon Gehr wrote:
 _.member is also missing.
`_.member` could break existing code, sorry. :(
Nov 21 2022
parent reply Nick Treleaven <nick geany.org> writes:
On Tuesday, 22 November 2022 at 04:17:37 UTC, IchorDev wrote:
 On Tuesday, 22 November 2022 at 01:43:25 UTC, Timon Gehr wrote:
 _.member is also missing.
`_.member` could break existing code, sorry. :(
I think only if someone named a variable `_`. That does not seem a sensible variable name to use and any breakage of that is justified IMO. I know it's sometimes used as a function name for translations - though because that requires an argument I think that distinguishes it from possible use for ETI. The nice thing about this syntax (ironically) is it's already an expression so: 1. it's more intuitive than using a new sigil. It looks like accessing a member of something, which it is. Underscore is often used in other languages to mean don't care, i.e. infer the parent type. (In cppfront you can use underscore instead of a function parameter type and the type will be inferred). 2. We aren't using up any syntax or reserving a sigil for this feature so there's more syntax available for any future features.
Nov 25 2022
next sibling parent reply XavierAP <n3minis-git yahoo.es> writes:
On Friday, 25 November 2022 at 19:40:35 UTC, Nick Treleaven wrote:
 On Tuesday, 22 November 2022 at 04:17:37 UTC, IchorDev wrote:
 On Tuesday, 22 November 2022 at 01:43:25 UTC, Timon Gehr wrote:
 _.member is also missing.
`_.member` could break existing code, sorry. :(
I think only if someone named a variable `_`. That does not seem a sensible variable name to use and any breakage of that is justified IMO. I know it's sometimes used as a function name for translations - though because that requires an argument I think that distinguishes it from possible use for ETI. The nice thing about this syntax (ironically) is it's already an expression so: 1. it's more intuitive than using a new sigil. It looks like accessing a member of something, which it is. Underscore is often used in other languages to mean don't care, i.e. infer the parent type. (In cppfront you can use underscore instead of a function parameter type and the type will be inferred). 2. We aren't using up any syntax or reserving a sigil for this feature so there's more syntax available for any future features.
Right on. But... Why then not not go one step further, and leave it up to each one's private code to alias _ = EType; when desired, and leave the language and backwards compatibility alone?
Nov 26 2022
next sibling parent reply cc <cc nevernet.com> writes:
On Saturday, 26 November 2022 at 11:14:05 UTC, XavierAP wrote:
 But... Why then not not go one step further, and leave it up to 
 each one's private code to

     alias _ = EType;

 when desired, and leave the language and backwards 
 compatibility alone?
Then you just have more escalating noise around every location where such aliases are needed. Having to copy/paste: ```d alias A = AttackType; alias W = WeaponType; alias M = MovementType; ``` is unideal. And the broader the scope they're declared in the more likely they are to conflict with other shortened alias names. And then when you have, say `enum EntityState` and `enum EnemySprite`, what then? `alias ETS`, `alias ESPR`... just further increasing symbolic clutter and cognitive load.
Nov 26 2022
parent reply XavierAP <n3minis-git yahoo.es> writes:
On Sunday, 27 November 2022 at 03:28:06 UTC, cc wrote:
 Having to copy/paste:
 ```d
 alias A = AttackType;
 alias W = WeaponType;
 alias M = MovementType;
 ```
 is unideal.  And the broader the scope they're declared in the 
 more likely they are to conflict with other shortened alias 
 names.

 And then when you have, say `enum EntityState` and `enum 
 EnemySprite`, what then?  `alias ETS`, `alias ESPR`... just 
 further increasing symbolic clutter and cognitive load.
Indeed here we hit the whole rationale of the DIP. Current enum from C purposely. I see how it can be tedious when importing C enums named in compensation e.g. IMG_INIT.IMG_INIT_jpg. In these or other exceptional cases aliasing can help. But as a general practice shortening names for the sake of shortness is very bad practice. This is more genenral than enums, and recommended in the literature. Certainly in the company where I work, if I use non-self-explanatory or even abbreviated names (e.g. A, W, E) my pull request won't be approved until I make them readable. I do the same consideration when reviewing other people's PRs. As I said in my first reply, the DIP provides no rationale other than current synatx "can be tedious" without providing any use case. It looks to me that the actual rationale of this change is (orher than dealing with badly named enums imported from C) to enable unreadable coding styles. And to mortgage the language and the compiler for it.
Nov 26 2022
next sibling parent bachmeier <no spam.net> writes:
On Sunday, 27 November 2022 at 07:48:48 UTC, XavierAP wrote:

 But as a general practice shortening names for the sake of 
 shortness is very bad practice.
Particularly when you shorten it to an ambiguous `$`, or just remove the name altogether.
Nov 27 2022
prev sibling parent ryuukk_ <ryuukk.dev gmail.com> writes:
On Sunday, 27 November 2022 at 07:48:48 UTC, XavierAP wrote:
 On Sunday, 27 November 2022 at 03:28:06 UTC, cc wrote:
 Having to copy/paste:
 ```d
 alias A = AttackType;
 alias W = WeaponType;
 alias M = MovementType;
 ```
 is unideal.  And the broader the scope they're declared in the 
 more likely they are to conflict with other shortened alias 
 names.

 And then when you have, say `enum EntityState` and `enum 
 EnemySprite`, what then?  `alias ETS`, `alias ESPR`... just 
 further increasing symbolic clutter and cognitive load.
Indeed here we hit the whole rationale of the DIP. Current enum from C purposely. I see how it can be tedious when importing C enums named in compensation e.g. IMG_INIT.IMG_INIT_jpg. In these or other exceptional cases aliasing can help. But as a general practice shortening names for the sake of shortness is very bad practice. This is more genenral than enums, and recommended in the literature. Certainly in the company where I work, if I use non-self-explanatory or even abbreviated names (e.g. A, W, E) my pull request won't be approved until I make them readable. I do the same consideration when reviewing other people's PRs. As I said in my first reply, the DIP provides no rationale other than current synatx "can be tedious" without providing any use case. It looks to me that the actual rationale of this change is (orher than dealing with badly named enums imported from C) to enable unreadable coding styles. And to mortgage the language and the compiler for it.
 the DIP provides no rationale other than current synatx "can be 
 tedious" without providing any use case.
Wrong, i even personally provided use cases by replying to your threads, you seem to ignore them improve C enums, they made them worse more verbose and less just recently) Thankfully the languages that stray away from C did enums and designated initialization of types right! Swift and Zig and to a lesser extent Kotlin for example
Nov 27 2022
prev sibling parent Nick Treleaven <nick geany.org> writes:
On Saturday, 26 November 2022 at 11:14:05 UTC, XavierAP wrote:
 But... Why then not not go one step further, and leave it up to 
 each one's private code to

     alias _ = EType;

 when desired, and leave the language and backwards 
 compatibility alone?
Firstly I don't think it would break backwards compatibility in practice, see my reply to cc. Secondly `alias` or `with` often does not help *at all* when you want type inference, and type inference already works with function literals: ```d enum LongName { a,b,c } LongName e; void function(int) f; void main() { f = (int i){}; f = (i){}; // infer parameter type e = LongName.a; e = $a; // infer parent type } ```
Nov 27 2022
prev sibling parent reply cc <cc nevernet.com> writes:
On Friday, 25 November 2022 at 19:40:35 UTC, Nick Treleaven wrote:
 On Tuesday, 22 November 2022 at 04:17:37 UTC, IchorDev wrote:
 On Tuesday, 22 November 2022 at 01:43:25 UTC, Timon Gehr wrote:
 `_.member` could break existing code, sorry. :(
I think only if someone named a variable `_`. That does not seem a sensible variable name to use and any breakage of that is justified IMO. I know it's sometimes used as a function name for translations - though because that requires an argument I think that distinguishes it from possible use for ETI.
`$_` is the default variable in perl (or was). I can potentially envision people using `_` as an iterator, match result, bitfield padding variable, etc. Whether that's a big enough issue worth worrying about, eh. Though it does seem odd have to make the exception "`_` is a word character, you can use it in any symbol name, except by itself." Suppose that's essentially the same situation for keywords, though. Is `..` used anywhere besides slicing and `foreach`? Just throwing that onto the pile, though it's probably another tool-breaker.
Nov 26 2022
parent Nick Treleaven <nick geany.org> writes:
On Sunday, 27 November 2022 at 03:17:45 UTC, cc wrote:
 `$_` is the default variable in perl (or was).  I can 
 potentially envision people using `_` as an iterator, match 
 result, bitfield padding variable, etc.  Whether that's a big 
 enough issue worth worrying about, eh.
Fair point, we would have to see how much code uses it. I don't think it's common in D.
 Though it does seem odd have to make the exception "`_` is a 
 word character, you can use it in any symbol name, except by 
 itself."  Suppose that's essentially the same situation for 
 keywords, though.
I wasn't necessarily arguing that underscore should not work as a variable name, just that accessing `_.foo` should try to match an enum member *when an enum member is expected* rather than a member of whatever `_` would otherwise evaluate to. I doubt that would break code.
Nov 27 2022
prev sibling parent IchorDev <zxinsworld gmail.com> writes:
On Monday, 21 November 2022 at 20:12:59 UTC, Guillaume Piolat 
wrote:
 There is no .member syntax in your poll (which implies 
 deprecating existing one)
`.identifier` is in use already. This syntax cannot be used for ETI, as it would break existing code.
Nov 21 2022
prev sibling parent reply IchorDev <zxinsworld gmail.com> writes:
On Monday, 21 November 2022 at 16:23:51 UTC, IchorDev wrote:
 If you'd like to vote about what ETI syntax you'd prefer, I've 
 opened a poll to keep track of how many people like which 
 syntax.
 The options I've listed are limited to ones that don't break 
 compatibility with existing code. If you'd like an option 
 added, let me know.
 https://strawpoll.com/polls/PKglzqaGJyp
Something to note about the poll: If you don’t enter a proper name, I might not count your vote. Entering a name that’s recognisable helps. Please vote if you have the time! It'll help me figure out which option is most popular. :)
Nov 21 2022
parent reply rikki cattermole <rikki cattermole.co.nz> writes:
On 22/11/2022 5:19 PM, IchorDev wrote:
 Please vote if you have the time! It'll help me figure out which option 
 is most popular. 😄
You left out "no syntax" so I can't vote for anything!
Nov 21 2022
parent reply IchorDev <zxinsworld gmail.com> writes:
On Tuesday, 22 November 2022 at 04:27:18 UTC, rikki cattermole 
wrote:
 On 22/11/2022 5:19 PM, IchorDev wrote:
 Please vote if you have the time! It'll help me figure out 
 which option is most popular. 😄
You left out "no syntax" so I can't vote for anything!
That's not a meaningful preference for the sake of "which one should the DIP propose in its next revision". For instance, if everyone voted for "no syntax" then the poll would be useless to me.
Nov 21 2022
parent reply rikki cattermole <rikki cattermole.co.nz> writes:
On 22/11/2022 6:47 PM, IchorDev wrote:
 For instance, if everyone voted for "no syntax" then the poll would be 
 useless to me.
But it would tell you something useful. It would suggest a lot of people are wanting to explore semantic behavior instead. Such as Walter's alternative proposal idea.
Nov 21 2022
parent reply bauss <jacobbauss gmail.com> writes:
On Tuesday, 22 November 2022 at 05:55:04 UTC, rikki cattermole 
wrote:
 On 22/11/2022 6:47 PM, IchorDev wrote:
 For instance, if everyone voted for "no syntax" then the poll 
 would be useless to me.
But it would tell you something useful. It would suggest a lot of people are wanting to explore semantic behavior instead. Such as Walter's alternative proposal idea.
If it's not implemented with .identifier then I will oppose it. I don't buy the "it will break code" point of view either. The only thing I can think of that will break is that .identifier already has a meaning today that means module scope. But that could easily mean module AND "static/scoped" lookup and any ambiguity can be fixed by prioritization. 1. module scope 2. enum 3. static members of ex. classes So if you type .a then it will first look in module scope, then in enums that are in scope and at last within classes that are in scope. I suggested something like it earlier too. Anything that is more complicated than .identifier is not worth it and will only introduce unncessary complexity to the language syntax. Example: ```d class A { static int a = 1; static int b = 2; } enum B { b = 3, c = 4 } int c = 5; void main() { writeln(.a); writeln(.b); writeln(.c); } ``` Prints: 1 3 5
Nov 22 2022
next sibling parent reply zjh <fqbqrr 163.com> writes:
On Tuesday, 22 November 2022 at 09:37:43 UTC, bauss wrote:

 Example:

 ```d
 class A { static int a = 1; static int b = 2; }
 enum B { b = 3, c = 4 }
 int c = 5;

 void main() {
   writeln(.a);
   writeln(.b);
   writeln(.c);
 }
 ```

 Prints:

 1
 3
 5
```d class A { static int a = 1; static int b = 2; } enum B { b = 3, c = 4 } int c = 5; void main() { with A,B; writeln(a); writeln(b); writeln(c); } ```
Nov 22 2022
parent zjh <fqbqrr 163.com> writes:
On Tuesday, 22 November 2022 at 10:06:24 UTC, zjh wrote:

 ```d
 class A { static int a = 1; static int b = 2; }
 enum B { b = 3, c = 4 }
 int c = 5;

 void main() {
   with A,B;
   writeln(a);
   writeln(b);
   writeln(c);
 }
 ```
Here are two `b`, disambiguation is required in any case.
Nov 22 2022
prev sibling next sibling parent IGotD- <nise nise.com> writes:
On Tuesday, 22 November 2022 at 09:37:43 UTC, bauss wrote:
 If it's not implemented with .identifier then I will oppose it.

 I don't buy the "it will break code" point of view either.

 The only thing I can think of that will break is that 
 .identifier already has a meaning today that means module scope.

 But that could easily mean module AND "static/scoped" lookup 
 and any ambiguity can be fixed by prioritization.

 1. module scope 2. enum 3. static members of ex. classes

 So if you type .a then it will first look in module scope, then 
 in enums that are in scope and at last within classes that are 
 in scope.

 I suggested something like it earlier too.

 Anything that is more complicated than .identifier is not worth 
 it and will only introduce unncessary complexity to the 
 language syntax.

 Example:

 ```d
 class A { static int a = 1; static int b = 2; }
 enum B { b = 3, c = 4 }
 int c = 5;

 void main() {
   writeln(.a);
   writeln(.b);
   writeln(.c);
 }
 ```

 Prints:

 1
 3
 5
I agree with this. In general the D project has become "don't break my beautiful parser/lexer" rather than what languages are supposed to do which is helping humans create/read code. Another thing is that globals are in general sparse so that there will likely not be an ambiguity between enums and globals. There is a higher likely hood that there will be a ambiguity between locals/members and enums with the syntax without the '.'. The . syntax is used in several other languages which helps and also it also helps the programmer understanding that it is an enum and not variable of any kind.
Nov 22 2022
prev sibling next sibling parent reply claptrap <clap trap.com> writes:
On Tuesday, 22 November 2022 at 09:37:43 UTC, bauss wrote:
 On Tuesday, 22 November 2022 at 05:55:04 UTC, rikki cattermole 
 wrote:
 On 22/11/2022 6:47 PM, IchorDev wrote:
 For instance, if everyone voted for "no syntax" then the poll 
 would be useless to me.
But it would tell you something useful. It would suggest a lot of people are wanting to explore semantic behavior instead. Such as Walter's alternative proposal idea.
If it's not implemented with .identifier then I will oppose it. I don't buy the "it will break code" point of view either. The only thing I can think of that will break is that .identifier already has a meaning today that means module scope. But that could easily mean module AND "static/scoped" lookup and any ambiguity can be fixed by prioritization. 1. module scope 2. enum 3. static members of ex. classes So if you type .a then it will first look in module scope, then in enums that are in scope and at last within classes that are in scope.
Why not an error if it's ambiguous? There are ways to specify which you want if needed. And its probably unlikely enough that occasionally having to specify the enum name is not anything to be concerned about.
Nov 22 2022
next sibling parent claptrap <clap trap.com> writes:
On Tuesday, 22 November 2022 at 12:27:41 UTC, claptrap wrote:
 On Tuesday, 22 November 2022 at 09:37:43 UTC, bauss wrote:
 On Tuesday, 22 November 2022 at 05:55:04 UTC, rikki cattermole 
 wrote:
 So if you type .a then it will first look in module scope, 
 then in enums that are in scope and at last within classes 
 that are in scope.
Why not an error if it's ambiguous? There are ways to specify which you want if needed. And its probably unlikely enough that occasionally having to specify the enum name is not anything to be concerned about.
Maybe somebody could scan some github repos and find out how often there's an enum member name that clashes with something in module scope? Would that be hard to do?
Nov 22 2022
prev sibling next sibling parent bauss <jacobbauss gmail.com> writes:
On Tuesday, 22 November 2022 at 12:27:41 UTC, claptrap wrote:
 On Tuesday, 22 November 2022 at 09:37:43 UTC, bauss wrote:
 On Tuesday, 22 November 2022 at 05:55:04 UTC, rikki cattermole 
 wrote:
 On 22/11/2022 6:47 PM, IchorDev wrote:
 For instance, if everyone voted for "no syntax" then the 
 poll would be useless to me.
But it would tell you something useful. It would suggest a lot of people are wanting to explore semantic behavior instead. Such as Walter's alternative proposal idea.
If it's not implemented with .identifier then I will oppose it. I don't buy the "it will break code" point of view either. The only thing I can think of that will break is that .identifier already has a meaning today that means module scope. But that could easily mean module AND "static/scoped" lookup and any ambiguity can be fixed by prioritization. 1. module scope 2. enum 3. static members of ex. classes So if you type .a then it will first look in module scope, then in enums that are in scope and at last within classes that are in scope.
Why not an error if it's ambiguous? There are ways to specify which you want if needed. And its probably unlikely enough that occasionally having to specify the enum name is not anything to be concerned about.
An error with ambiguity is fine, BUT I think it shouldn't happen in the cases I provided, it should only happen in cases you have two symbols with same priority. So no error should be displayed if a global is named "a" and an enum member is named "a", BUT it should have an error if there are two enum members named "a", UNLESS there is also a global named "a".
Nov 22 2022
prev sibling parent reply Paul Backus <snarwin gmail.com> writes:
On Tuesday, 22 November 2022 at 12:27:41 UTC, claptrap wrote:
 Why not an error if it's ambiguous? There are ways to specify 
 which you want if needed. And its probably unlikely enough that 
 occasionally having to specify the enum name is not anything to 
 be concerned about.
Error on ambiguity can break existing code. For example, this currently compiles, but would become ambiguous if we added enum type inference using .identifier syntax: enum E { x = 123 } int x = 456; static assert(.x == 456); If we wanted to avoid breaking existing code, we would have to ensure that module-scope lookup *always* took precedence over enum member lookup. Of course, the module scope .identifier syntax is not very widely used in the first place, so maybe a small risk of breakage is worth the benefit of nice syntax for enum members.
Nov 22 2022
parent reply Guillaume Piolat <first.last spam.org> writes:
On Tuesday, 22 November 2022 at 19:10:18 UTC, Paul Backus wrote:
 Of course, the module scope .identifier syntax is not very 
 widely used in the first place, so maybe a small risk of 
 breakage is worth the benefit of nice syntax for enum members.
.identifier syntax meaning module scope is not especially intuitive. We got used to it with ::identifier in C++, and it got imported from there. It could be something explicit like module.identifier
Nov 23 2022
parent Adam D Ruppe <destructionator gmail.com> writes:
On Wednesday, 23 November 2022 at 22:25:04 UTC, Guillaume Piolat 
wrote:
 It could be something explicit like module.identifier
This isn't quite the same as .identifier, since `module.identifier` looks up ident specifically in module, whereas .identifier just bypasses the local name and might refer to a local thing, or in an imported thing. module foo; .destroy() // often refers to object.destroy() rather than foo.destroy() So it would take a little effort if these things had to be ported.
Nov 23 2022
prev sibling next sibling parent reply Guillaume Piolat <first.last spam.org> writes:
On Tuesday, 22 November 2022 at 09:37:43 UTC, bauss wrote:
 If it's not implemented with .identifier then I will oppose it.
+1 and it's a feature that was desperately needed anyway.
Nov 23 2022
next sibling parent Guillaume Piolat <first.last spam.org> writes:
On Wednesday, 23 November 2022 at 22:16:35 UTC, Guillaume Piolat 
wrote:
 On Tuesday, 22 November 2022 at 09:37:43 UTC, bauss wrote:
 If it's not implemented with .identifier then I will oppose it.
+1 and it's a feature that was desperately needed anyway.
that was *not* desperately needed
Nov 23 2022
prev sibling next sibling parent reply Adam D Ruppe <destructionator gmail.com> writes:
On Wednesday, 23 November 2022 at 22:16:35 UTC, Guillaume Piolat 
wrote:
 On Tuesday, 22 November 2022 at 09:37:43 UTC, bauss wrote:
 If it's not implemented with .identifier then I will oppose it.
+1
So that's two "no" votes to the feature.
Nov 23 2022
parent cc <cc nevernet.com> writes:
On Wednesday, 23 November 2022 at 22:22:23 UTC, Adam D Ruppe 
wrote:
 On Wednesday, 23 November 2022 at 22:16:35 UTC, Guillaume 
 Piolat wrote:
 On Tuesday, 22 November 2022 at 09:37:43 UTC, bauss wrote:
 If it's not implemented with .identifier then I will oppose 
 it.
+1
So that's two "no" votes to the feature.
Not a DIP contributor, but if it's open voting, I like Walter's alternative of no punctuation, if possible. Otherwise I have no particular opinion on which character, `.indentifier` is fine, but `$` feels like I'm writing perl again, not very attractive. :/ Would absolutely use this feature, though. Have similar use cases to ryuukk_'s examples.
Nov 24 2022
prev sibling parent reply Dukc <ajieskola gmail.com> writes:
On Wednesday, 23 November 2022 at 22:16:35 UTC, Guillaume Piolat 
wrote:
 On Tuesday, 22 November 2022 at 09:37:43 UTC, bauss wrote:
 If it's not implemented with .identifier then I will oppose it.
+1 and it's a feature that was desperately needed anyway.
It's exactly the other way IMO -- whether the feature gets in at all, and the technical considerations of it are more important. As a programmer, whether the syntax will be `$identifier`, `.identifier`, `_.identifier`, `$.identifier`, `#identifier`, debate which of these looks the best, but disagreements of taste on questions like that should not block the DIP. There is only so much free time to spend on writing and implementing DIPs so let's not increase the bar by vetoing on grounds like this. You're demanding `.identifier` for a better reason - that is, avoiding reserving any new syntax. I don't agree with that either, but at least it's a technical argument as opposed to mere bikeshedding. So I'm not singling you two with what I wrote above, instead I'm aiming at this thread in general.
Nov 25 2022
parent IGotD- <nise nise.com> writes:
On Friday, 25 November 2022 at 09:53:34 UTC, Dukc wrote:
 It's exactly the other way IMO -- whether the feature gets in 
 at all, and the technical considerations of it are more 
 important. As a programmer, whether the syntax will be 
 `$identifier`, `.identifier`, `_.identifier`, `$.identifier`, 
 `#identifier
 We can of course debate which of these looks the best, but 
 disagreements of taste on questions like that should not block 
 the DIP.

 You're demanding `.identifier` for a better reason - that is, 
 avoiding reserving any new syntax. I don't agree with that 
 either, but at least it's a technical argument as opposed to 
 mere bikeshedding. So I'm not singling you two with what I 
 wrote above, instead I'm aiming at this thread in general.
Syntax aesthetics play a big part in language design. Also alignment with other popular languages is also an argument. Yes, if the syntax of a new feature looks like a behind of camel, then it is better that the feature is postponed.
Nov 25 2022
prev sibling parent reply IchorDev <zxinsworld gmail.com> writes:
On Tuesday, 22 November 2022 at 09:37:43 UTC, bauss wrote:
 If it's not implemented with .identifier then I will oppose it.

 I don't buy the "it will break code" point of view either.

 [...] if you type .a then it will first look in module scope, 
 then in enums that are in scope and at last within classes that 
 are in scope.

 I suggested something like it earlier too.

 Anything that is more complicated than .identifier is not worth 
 it and will only introduce unncessary complexity to the 
 language syntax.
`.identifier` has a multitude of issues, actually. Doing this crazy "just ignore ETI if it coincides with module scope operator" idea was one I had before I wrote the DIP. It's clever, but it has a few major flaws. 1. Performance. Every time you try to use ETI, you're also triggering a module-scope lookup *every* time you compile your code. How would you know something like that without being told? 2. Intuitiveness. Nobody would understand this behaviour without a brief history lesson and a thorough explanation of how module vs. local vs. external variable lookup works. That might sound pretty simple to you, but to a new programmer that is a cluster-headache worth of information to take into account... just to use a shortcut. 3. Flexibility. Oops, did you just name a module-level variable "water"? Well, now you can't use ETI on the "water" member of your "Elements" enum! Why is that? Because we decided to try and fit two features into one operator. :) 4. Future expansion. Fitting *two* features into `.identifier` leaves type inference very little room for future expansion. Considering the other 3 issues, I think it would kill any possibility of type inference being added for other language features. `$identifier` is less complicated, which is part of how it's most of the way through being implemented already.
Nov 24 2022
parent bauss <jacobbauss gmail.com> writes:
On Thursday, 24 November 2022 at 14:36:26 UTC, IchorDev wrote:
 On Tuesday, 22 November 2022 at 09:37:43 UTC, bauss wrote:
 If it's not implemented with .identifier then I will oppose it.

 I don't buy the "it will break code" point of view either.

 [...] if you type .a then it will first look in module scope, 
 then in enums that are in scope and at last within classes 
 that are in scope.

 I suggested something like it earlier too.

 Anything that is more complicated than .identifier is not 
 worth it and will only introduce unncessary complexity to the 
 language syntax.
`.identifier` has a multitude of issues, actually. Doing this crazy "just ignore ETI if it coincides with module scope operator" idea was one I had before I wrote the DIP. It's clever, but it has a few major flaws. 1. Performance. Every time you try to use ETI, you're also triggering a module-scope lookup *every* time you compile your code. How would you know something like that without being told? 2. Intuitiveness. Nobody would understand this behaviour without a brief history lesson and a thorough explanation of how module vs. local vs. external variable lookup works. That might sound pretty simple to you, but to a new programmer that is a cluster-headache worth of information to take into account... just to use a shortcut. 3. Flexibility. Oops, did you just name a module-level variable "water"? Well, now you can't use ETI on the "water" member of your "Elements" enum! Why is that? Because we decided to try and fit two features into one operator. :) 4. Future expansion. Fitting *two* features into `.identifier` leaves type inference very little room for future expansion. Considering the other 3 issues, I think it would kill any possibility of type inference being added for other language features. `$identifier` is less complicated, which is part of how it's most of the way through being implemented already.
$identifier is ugly IMHO and anything that requires any new operators is just not worth it. As I stated before then I am against this DIP. The feature isn't that important that I want code to be cluttered with new syntax that hardly adds anything.
Nov 24 2022
prev sibling next sibling parent reply TheGag96 <thegag96 gmail.com> writes:
On the topic of the `:ident` syntax: It sounded good at first, 
but then I thought about our struct initialization syntax and our 
new named arguments syntax:

```d
ColorPair pair = {
   fg : :red,
   bg : :green,
}

someFunc(fg : :red, bg: :green);
```

Seems kind of ugly. `.identifier` and `#identifier` are the best 
options IMO (but both unavailable lol). Implicit is decent I 
guess but looks kind of spooky.
Nov 22 2022
parent IchorDev <zxinsworld gmail.com> writes:
On Tuesday, 22 November 2022 at 15:42:27 UTC, TheGag96 wrote:
 On the topic of the `:ident` syntax: It sounded good at first, 
 but then I thought about our struct initialization syntax and 
 our new named arguments syntax:

 ```d
 ColorPair pair = {
   fg : :red,
   bg : :green,
 }

 someFunc(fg : :red, bg: :green);
 ```

 Seems kind of ugly. `.identifier` and `#identifier` are the 
 best options IMO (but both unavailable lol). Implicit is decent 
 I guess but looks kind of spooky.
Hmm. `#identifier` is so nice huh. I know `#line` might be niche, but I don't want to break it. It's got to be pretty useful for automated bindings. It is such a small part of the language that the thought crossed my mind, but I don't think the people using it would be pleased.
Nov 22 2022
prev sibling next sibling parent reply XavierAP <n3minis-git yahoo.es> writes:
On Friday, 18 November 2022 at 15:37:31 UTC, Mike Parker wrote:


 This is the discussion thread for the first round of Community 
 Review of DIP 1044, "Enum Type Inference":

 https://github.com/dlang/DIPs/blob/e2ca557ab9d3e60305a37da0d5b58299e0a9de0e/DIPs/DIP1044.md
At the very least I would require the "rationale" to say something more than "can be tedious" or at least provide a use case thereof (which cannot have a better solution within the existing language). I concur about the $, looks terrible. And why is it better to type "$" than "Type."? Is it because your enum names are too long (in some context)? Just alias them.
Nov 22 2022
parent reply IchorDev <zxinsworld gmail.com> writes:
On Tuesday, 22 November 2022 at 21:47:28 UTC, XavierAP wrote:
 On Friday, 18 November 2022 at 15:37:31 UTC, Mike Parker wrote:


 This is the discussion thread for the first round of Community 
 Review of DIP 1044, "Enum Type Inference":

 https://github.com/dlang/DIPs/blob/e2ca557ab9d3e60305a37da0d5b58299e0a9de0e/DIPs/DIP1044.md
At the very least I would require the "rationale" to say something more than "can be tedious" or at least provide a use case thereof (which cannot have a better solution within the existing language). I concur about the $, looks terrible. And why is it better to type "$" than "Type."? Is it because your enum names are too long (in some context)? Just alias them.
Aliasing requires figuring out a good alias name, polluting the namespace, and just feels like a hack. It's nice that D lets you, but I think a dedicated mechanism to reduce typing fatigue is better than obfuscation. "What's this... `M`?" *searches library* "What? This isn't in here!" *searches codebase* "Oh, it's an alias of `Magic`. Who did this?" vs "`$`? Oh, this function call uses ETI. Let me see its declaration..." *checks declaration* "Okay it's `Magic`"
Nov 22 2022
next sibling parent XavierAP <n3minis-git yahoo.es> writes:
On Wednesday, 23 November 2022 at 04:43:16 UTC, IchorDev wrote:
 Is it because your enum names are too long (in some context)? 
 Just alias them.
Aliasing requires figuring out a good alias name, polluting the namespace, and just feels like a hack. It's nice that D lets you, but I think a dedicated mechanism to reduce typing fatigue is better than obfuscation.
I agree aliasing should in general be avoided (certainly never down to single letters) in favor of good, readable names overall. It can help you when importing third party stuff whose names are bad overall or have room for improvement in your context.
Nov 23 2022
prev sibling parent reply bachmeier <no spam.net> writes:
On Wednesday, 23 November 2022 at 04:43:16 UTC, IchorDev wrote:

 Aliasing requires figuring out a good alias name, polluting the 
 namespace, and just feels like a hack.
Naming stuff is a technique that has been used in programming languages for quite a while. It's a feature I can't do without. Finding good names for things is indeed important. And polluting the namespace is bad. I don't know what that has to do with this DIP or with alias. I also don't agree that naming things is a hack.
 It's nice that D lets you, but I think a dedicated mechanism to 
 reduce typing fatigue is better than obfuscation.
Then find a better editor/IDE. One that has copy and paste.
 "What's this... `M`?" *searches library* "What? This isn't in 
 here!" *searches codebase* "Oh, it's an alias of `Magic`. Who 
 did this?"
 vs
 "`$`? Oh, this function call uses ETI. Let me see its 
 declaration..." *checks declaration* "Okay it's `Magic`"
This is absurd. The DIP proposes using the same `$` to refer to *any* enum. If someone is confused by an explicit name, by definition they're going to be confused by a generic `$`.
Nov 23 2022
parent IchorDev <zxinsworld gmail.com> writes:
On Wednesday, 23 November 2022 at 15:24:42 UTC, bachmeier wrote:
 I also don't agree that naming things is a hack.
You've overlooked my argument that giving *two names* to *the same thing* to avoid writing a longer name is a hack. The compiler knows what type you should enter and so do you? Great, don't need to write it. On Wednesday, 23 November 2022 at 15:24:42 UTC, bachmeier wrote:
 Then find a better editor/IDE. One that has copy and paste.
This "helpful advice" does not help at all, it's condescending and rude. Not to mention, your argument is completely reversible. If you don't like ETI because it allows other people to write code that's not verbose enough for you, then find an editor/IDE that displays the types anyway. On Wednesday, 23 November 2022 at 15:24:42 UTC, bachmeier wrote:
 The DIP proposes using the same `$` to refer to *any* enum.
No. `$member` can **only** refer to a member of an enum that **has to be inferred through context**. Like the type of a function parameter, or the type of a struct field. ```d enum A{ a,b,c,d } enum B{ a,b,c,d } struct S{ A one; B two; } void myFn(A param); void main(){ myFn($a); // passes A.a S myS = S($c, $d); //myS = S(A.c, B.d); myS.one = $b; //myS = S(A.b, B.d); } ``` On Wednesday, 23 November 2022 at 15:24:42 UTC, bachmeier wrote:
 If someone is confused by an explicit name, by definition 
 they're going to be confused by a generic `$`.
If the explicit name is a *local alias* that doesn't match what they expect when using a *library*, causing them to search the documentation for the *library*, and not for a local alias to something from that library then yes, it is going to waste their time. That's a big issue with reading aliases: that they're identical to a non-aliased type name, and are generally treated the same way by programmers and the compiler. ETI replaces the type identifier with a unique unary operator, so you can *know* that you *don't know* the type.
Nov 24 2022
prev sibling next sibling parent reply IchorDev <zxinsworld gmail.com> writes:
Nobody mentioned it here yet, so I figured I'd point out that the 
wonderful UplinkCoder has made a partial implementation of this 
DIP.
You can find the PR for it here: 
https://github.com/dlang/dmd/pull/14650

They have implemented a great deal of the proposed features in 
less than a day. They said ETI overloaded functions are 
incomplete and may take some time to finish, but I think that 
their progress so far demonstrates just how simple a feature ETI 
really is.
Nov 22 2022
parent Stefan Koch <uplink.coder googlemail.com> writes:
On Wednesday, 23 November 2022 at 05:01:58 UTC, IchorDev wrote:
 Nobody mentioned it here yet, so I figured I'd point out that 
 the wonderful UplinkCoder has made a partial implementation of 
 this DIP.
 You can find the PR for it here: 
 https://github.com/dlang/dmd/pull/14650

 They have implemented a great deal of the proposed features in 
 less than a day. They said ETI overloaded functions are 
 incomplete and may take some time to finish, but I think that 
 their progress so far demonstrates just how simple a feature 
 ETI really is.
Thanks for mentioning it. I think overloaded functions should work now. The cause of the issue turned out to be a straightforward bug in my code. which caused the type to be set even if the enum member inference failed. Which meant the expression got typed as the first enum declared in the. Simply moving the setting of the type until after the check for a vaild inference; Fixed that bug. TLDR; the PR _should_ now implement the DIP largely the way it's discribed.
Nov 23 2022
prev sibling next sibling parent reply XavierAP <n3minis-git yahoo.es> writes:
On Friday, 18 November 2022 at 15:37:31 UTC, Mike Parker wrote:
 https://github.com/dlang/DIPs/blob/e2ca557ab9d3e60305a37da0d5b58299e0a9de0e/DIPs/DIP1044.md
Another bad idea about this is that it reserves «$» for this purpose, which we may in the future wish we had available for some other worthier feature/paradigm. Apparently choosing «.» instead creates other conflicts.
Nov 23 2022
parent reply deadalnix <deadalnix gmail.com> writes:
On Wednesday, 23 November 2022 at 08:45:43 UTC, XavierAP wrote:
 On Friday, 18 November 2022 at 15:37:31 UTC, Mike Parker wrote:
 https://github.com/dlang/DIPs/blob/e2ca557ab9d3e60305a37da0d5b58299e0a9de0e/DIPs/DIP1044.md
Another bad idea about this is that it reserves «$» for this purpose, which we may in the future wish we had available for some other worthier feature/paradigm. Apparently choosing «.» instead creates other conflicts.
This is indeed a concern. C++ ran out of good syntax, so now every single thing is some convoluted mess. We don't have to take the same road.
Nov 23 2022
parent RTM <riven baryonides.ru> writes:
 On Friday, 18 November 2022 at 15:37:31 UTC, Mike Parker wrote:
https://github.com/dlang/DIPs/blob/e2ca557ab9d3e60305a37da0d5b58299e0a9de0e/DIPs/DIP1044.md
It looks redundant (“with” and “alias” is enough IMHO).
Nov 23 2022
prev sibling parent reply Ishax <isaacbunsen gmail.com> writes:
 This DIP proposes that ETI in D should use the syntax 
 $enumMember.
Why not extend this to apply to all things inside namespaces such as static class members, or the items of a statically imported package?
Nov 23 2022
parent XavierAP <n3minis-git yahoo.es> writes:
On Wednesday, 23 November 2022 at 17:24:53 UTC, Ishax wrote:
 This DIP proposes that ETI in D should use the syntax 
 $enumMember.
Why not extend this to apply to all things inside namespaces such as static class members, or the items of a statically imported package?
100% this (which would still be a bad idea imho, but not as bad as making this work just for enums)
Nov 23 2022