digitalmars.D - Enum literals, good? bad? what do you think?
- russhy (15/15) Jul 20 2021 Hello
- H. S. Teoh (37/42) Jul 20 2021 [...]
- russhy (6/49) Jul 20 2021 That's a good point, and that ``switch with`` is very nice and
- Max Samukha (2/9) Jul 20 2021 Cool hack!
- claptrap (15/34) Jul 20 2021 That's irrelevant i think, since #defines are like anonymous
- =?UTF-8?Q?Ali_=c3=87ehreli?= (27/33) Jul 20 2021 Most of the time yes, but our enums are not that strong. :) The
- claptrap (17/41) Jul 20 2021 That that would be an error since the parameter is an 'int' so
- =?UTF-8?Q?Ali_=c3=87ehreli?= (6/11) Jul 20 2021 Agreed. There wouldn't be name hijacking in that case. Either works
- Walter Bright (23/34) Jul 20 2021 In C, qualifying the member name with the tag name is not only not neces...
- Patrick Schluter (8/18) Jul 21 2021 mixin({
- Walter Bright (3/13) Jul 21 2021 Sweet!
- Mike Parker (15/25) Jul 21 2021 ```d
- Walter Bright (4/17) Jul 21 2021 You & Patrick are da men!
- Adam D Ruppe (9/12) Jul 21 2021 Eeek, this is awful. It uses .stringof which means it is
- Walter Bright (3/11) Jul 21 2021 How so?
- Adam D Ruppe (11/14) Jul 21 2021 That limits the usefulness, but you still might as well do it
- Walter Bright (4/14) Jul 21 2021 True, but that isn't specific to enums. D does not attempt to do overloa...
- Mike Parker (11/12) Jul 20 2021 Personally, I have no issue with the current setup. I like
- Paul Backus (12/14) Jul 20 2021 Currently, name lookup in D is done independently from
- Petar Kirov [ZombineDev] (28/44) Jul 21 2021 One could argue that function overloading is a case where name
- Walter Bright (3/5) Jul 21 2021 Struct literals can be anywhere once named parameters are implemented. T...
- Paul Backus (27/39) Jul 22 2021 IMO D's target-typed literals (also called "polysemous literals")
- John Colvin (4/29) Jul 22 2021 It’s not so bad IMO. Type inference in D isn’t far from just
- Basile B. (7/22) Jul 20 2021 In the past [I liked the
- Danni Coy (9/24) Jul 20 2021 When I work in C/C++ and other similar languages, I find that on
- Mathias LANG (22/24) Jul 20 2021 The `.` syntax is ambiguous because `.` is the module-scope
- Walter Bright (6/24) Jul 20 2021 If you want anonymous enums, use:
- Mathias LANG (9/19) Jul 21 2021 What I meant was that instead of recommending our users to use
- Walter Bright (14/22) Jul 21 2021 Ok, I see what you mean. If it was restricted to the case value expressi...
- Walter Bright (2/2) Jul 21 2021 I can see the Scott Meyers slide on "Quirks Of D" already:
- Mathias LANG (5/7) Jul 21 2021 That's a very good point, I didn't think about local enum when
- rikki cattermole (5/9) Jul 21 2021 If you can't describe it using words, use code instead.
- Walter Bright (3/4) Jul 22 2021 I tried everything, including that. I really cannot explain it. It was a...
- rikki cattermole (5/10) Jul 22 2021 Oh hmm. I just went looking for it, the only files regarding semantic
- Walter Bright (4/16) Jul 22 2021 The symbol lookup used to be very simple and completely consistent in D....
- Tejas (3/21) Jul 22 2021 You mean this isn't true anymore?
- zjh (12/15) Jul 21 2021 Because the forum can not label the post, and We didn't sort out
- Patrick Schluter (19/43) Jul 22 2021 This case is comparable to variable shadowing and should then be
- Patrick Schluter (21/45) Jul 22 2021 Currently, that's what happens
- Basile B. (3/6) Jul 22 2021 Sorry for the massive disapointment but it can :
- claptrap (6/15) Jul 22 2021 Sometimes i think the main problem with D is all these weird
- Walter Bright (6/9) Jul 22 2021 Programming languages aren't completely consistent because:
- Patrick Schluter (9/18) Jul 22 2021 ```d
- claptrap (2/5) Jul 22 2021 Its not a bug it's a feature!
- Basile B. (5/24) Jul 22 2021 Yes it is definitively a bug, I know it already but I could not
- Patrick Schluter (2/26) Jul 22 2021 Don't be sorry when what you say is true. :-)
- Basile B. (4/11) Jul 22 2021 bugzilla:
- zjh (5/6) Jul 20 2021 And the default constructor,
- russhy (3/9) Jul 21 2021 yes that too.. if you can create DIP draft for it and post it on
- Walter Bright (2/13) Jul 21 2021 It's been discussed many times. It comes up once a year or so.
- zjh (8/15) Jul 21 2021 I really don't understand. Isn't `d` called `pragmatism`?
- Paul Backus (5/20) Jul 21 2021 Initialization in C++ is described as a "nightmare" by
- zjh (2/4) Jul 21 2021 I am also `experienced ` C++ Programmer,why I don't hurt from it?
- Walter Bright (7/8) Jul 21 2021 There are many ways to experience C++.
- zjh (19/22) Jul 21 2021 As a `plain user`, I hope to have the same convenience as `C++`.
- zjh (11/15) Jul 21 2021 Primary users increase, promote the increase of lib writers,
- Walter Bright (6/23) Jul 22 2021 One of D's goals is to not have C++ features that cause more problems th...
- Steven Schveighoffer (21/44) Jul 21 2021 I enjoy having this type of shortcut in Swift, and wish D had something
- russhy (5/53) Jul 21 2021 of course the . syntax isn't final, the point of the DIP
- russhy (5/5) Jul 21 2021 of course the . syntax isn't final, the point of the DIP
- Walter Bright (3/4) Jul 21 2021 Your wish has been heard and duly granted. The internet delivers once ag...
- Steven Schveighoffer (3/11) Jul 21 2021 No, `mixin something; thenCallFunction(...);` isn't even close to the sa...
- Walter Bright (2/3) Jul 21 2021 I don't know what it is you're asking for, then.
- Steven Schveighoffer (38/43) Jul 22 2021 I'm not asking for anything. What I'm saying is the feature in Swift
- Walter Bright (12/35) Jul 22 2021 How does that interact with function overloading?
- Steven Schveighoffer (52/95) Jul 22 2021 Swift is known for "giving up" on expression inference, so possibly it
- Walter Bright (9/21) Jul 22 2021 So it appears that Swift simply gives an error if there's more than one ...
- Dukc (7/13) Jul 23 2021 It could work with bottom-up inference only. It would work the
- Paul Backus (11/14) Jul 23 2021 D is mostly "bottom up", but there are a few corner cases [1]
- Steven Schveighoffer (16/22) Jul 23 2021 I don't disagree. I think in your example here, it's not
- Dukc (10/11) Jul 21 2021 As mentioned by others, `enumVar = .memberName` is ambiguous with
- Paul Backus (5/16) Jul 21 2021 ```d
- Dukc (8/12) Jul 22 2021 The VRP mechanics do not currently let that compile, so nothing
- Paul Backus (5/19) Jul 22 2021 Ok, now imagine you're new to D and don't know about this
- bauss (2/17) Jul 22 2021 Terrible, just terrible.
Hello I all the time wondered why we always have to be so much verbose with enum, when it's not casting to primitives, it is about repeating their long type name, constantly, all the time After trying some other languages over the past few years, i discovered in zig you can just ommit the enum type name and just use enums this way: .MY_VALUE I don't know if that's something that could be supported with D, i am not a compiler dude, so i don't have the answer Adam on discord mentioned using with(ENUM_TYPE) or just an alias, but i think we go ahead and make it simple I had prepared a DIP [1], not ready at all, but i wanted to initiate some discussion about that feature So what do you think? yay? nay? why not? [1] https://github.com/RUSshy/DIPs/blob/patch-2/DIPs/DIP1xxx.md
Jul 20 2021
On Tue, Jul 20, 2021 at 03:50:49PM +0000, russhy via Digitalmars-d wrote:Hello I all the time wondered why we always have to be so much verbose with enum, when it's not casting to primitives, it is about repeating their long type name, constantly, all the time[...] OT1H, having to qualify enums by their full name is good, it helps to avoid the mess in C where libraries sometimes define conflicting values under the same name, e.g., // somelib.h #define ERROR 0 #define OK 1 // someotherlib.h #define ERROR -1 #define OK 0 In D, if you used an enum, you'd have to quality which ERROR or OK you're referring to, which avoids conflicts and also avoids unexpected symbol hijacking. E.g., somelib.h used to define MY_OK = 1, but after upgrading they renamed MY_OK to OK, now your code that referred to OK in someotherlib.h may accidentally get the wrong value. OTOH, I agree that sometimes D enums become rather verbose. Especially in switch statements where you have to repeat their name for every case. Fortunately, this is where D's `with` statement comes in helpful: enum MyEnum { blah, bleh, bluh } MyEnum val = ...; final switch (val) { case MyEnum.blah: ... case MyEnum.bleh: ... case MyEnum.bluh: ... } can be replaced with: enum MyEnum { blah, bleh, bluh } MyEnum val = ...; final switch (val) with (MyEnum) { case blah: ... // look ma! less repetition! case bleh: ... case bluh: ... } T -- Questions are the beginning of intelligence, but the fear of God is the beginning of wisdom.
Jul 20 2021
On Tuesday, 20 July 2021 at 16:12:05 UTC, H. S. Teoh wrote:On Tue, Jul 20, 2021 at 03:50:49PM +0000, russhy via Digitalmars-d wrote:That's a good point, and that ``switch with`` is very nice and solve the issue I didn't know about ``with`` until adam mentioned it, could the rule in ``switch`` be relaxed and implement something akin to ``with`` ?Hello I all the time wondered why we always have to be so much verbose with enum, when it's not casting to primitives, it is about repeating their long type name, constantly, all the time[...] OT1H, having to qualify enums by their full name is good, it helps to avoid the mess in C where libraries sometimes define conflicting values under the same name, e.g., // somelib.h #define ERROR 0 #define OK 1 // someotherlib.h #define ERROR -1 #define OK 0 In D, if you used an enum, you'd have to quality which ERROR or OK you're referring to, which avoids conflicts and also avoids unexpected symbol hijacking. E.g., somelib.h used to define MY_OK = 1, but after upgrading they renamed MY_OK to OK, now your code that referred to OK in someotherlib.h may accidentally get the wrong value. OTOH, I agree that sometimes D enums become rather verbose. Especially in switch statements where you have to repeat their name for every case. Fortunately, this is where D's `with` statement comes in helpful: enum MyEnum { blah, bleh, bluh } MyEnum val = ...; final switch (val) { case MyEnum.blah: ... case MyEnum.bleh: ... case MyEnum.bluh: ... } can be replaced with: enum MyEnum { blah, bleh, bluh } MyEnum val = ...; final switch (val) with (MyEnum) { case blah: ... // look ma! less repetition! case bleh: ... case bluh: ... } T
Jul 20 2021
On Tuesday, 20 July 2021 at 16:12:05 UTC, H. S. Teoh wrote:enum MyEnum { blah, bleh, bluh } MyEnum val = ...; final switch (val) with (MyEnum) { case blah: ... // look ma! less repetition! case bleh: ... case bluh: ... }Cool hack!
Jul 20 2021
On Tuesday, 20 July 2021 at 16:12:05 UTC, H. S. Teoh wrote:On Tue, Jul 20, 2021 at 03:50:49PM +0000, russhy via Digitalmars-d wrote:That's irrelevant i think, since #defines are like anonymous enums, and you dont need to save typing on those. With named enums in D i think you'd know (most or all? of the time) which one it is by the context... Eg.. enum SomeResult { OK, Error } enum OtherResult { Error, OK } You cant assign or pass SomeResult.OK to something that is expecting an OtherResult can you? So if you have a function... void handleError(OtherResult r); and call it thus... handleError(OK); You know it's OtherResult.OK Isnt that the point of strong typing?Hello I all the time wondered why we always have to be so much verbose with enum, when it's not casting to primitives, it is about repeating their long type name, constantly, all the time[...] OT1H, having to qualify enums by their full name is good, it helps to avoid the mess in C where libraries sometimes define conflicting values under the same name, e.g., // somelib.h #define ERROR 0 #define OK 1 // someotherlib.h #define ERROR -1 #define OK 0 In D, if you used an enum, you'd have to quality which ERROR or OK you're referring to, which avoids conflicts and also avoids
Jul 20 2021
On 7/20/21 1:43 PM, claptrap wrote:So if you have a function... void handleError(OtherResult r); and call it thus... handleError(OK); You know it's OtherResult.OK Isnt that the point of strong typing?Most of the time yes, but our enums are not that strong. :) The following compiles and runs with both types. enum Animal { Jaguar = 100 } enum Car { Jaguar = 42 } void foo(int i) { } void main() { foo(Animal.Jaguar); foo(Car.Jaguar); } But the your argument will probably be foo(Jaguar); should work as long as there is no conflict. But then there is name hijacking. What if that last expression worked and let's say only Car.Jaguar was in scope. What if I imported an unrelated module that defined this: int Jaguar = 0; I would expect foo(Jaguar) to still work with that int without complaints because I did not specify the enum version. But then my program works differently. (In other words, I would not expect the compiler to complain about a name conflict between an module-level name and an enum-protected name; that's the whole point anyway.) In any case, I don't have any problem with extra typing and happy with D's safer enums. I experimented with the with(Enum) helper but don't use it anymore. Not a big deal. :/ Ali
Jul 20 2021
On Tuesday, 20 July 2021 at 21:15:19 UTC, Ali Çehreli wrote:On 7/20/21 1:43 PM, claptrap wrote:That that would be an error since the parameter is an 'int' so you dont have any context to decide what enum it should refer to. IE.. void foo(int i); void bar(Animal a); foo(Animal.Jaguar); // OK foo(Jaguar); // Error bar(Jaguar); // OK likewise auto a = Jaguar; // Error Car c = Jaguar; // OK The point is you should only be able to drop the enum name if the parameter or the variable you're assigning to are ***named enums***. I suppose for switch you could do the same, if the variable being switched on is a named enum, then the cases can drop the name.So if you have a function... void handleError(OtherResult r); and call it thus... handleError(OK); You know it's OtherResult.OK Isnt that the point of strong typing?Most of the time yes, but our enums are not that strong. :) The following compiles and runs with both types. enum Animal { Jaguar = 100 } enum Car { Jaguar = 42 } void foo(int i) { } void main() { foo(Animal.Jaguar); foo(Car.Jaguar); } But the your argument will probably be foo(Jaguar);
Jul 20 2021
On 7/20/21 2:52 PM, claptrap wrote:The point is you should only be able to drop the enum name if the parameter or the variable you're assigning to are ***named enums***.Agreed. There wouldn't be name hijacking in that case. Either works helpfully or errors with a conflict.I suppose for switch you could do the same, if the variable being switched on is a named enum, then the cases can drop the name.Agreed with that as well. The type of the switch variable could hint the compiler. Ali
Jul 20 2021
On 7/20/2021 9:12 AM, H. S. Teoh wrote:OTOH, I agree that sometimes D enums become rather verbose. Especially in switch statements where you have to repeat their name for every case. Fortunately, this is where D's `with` statement comes in helpful: enum MyEnum { blah, bleh, bluh } MyEnum val = ...; final switch (val) { case MyEnum.blah: ... case MyEnum.bleh: ... case MyEnum.bluh: ... }In C, qualifying the member name with the tag name is not only not necessary, it is not allowed. Hence, here how C does it: enum MyEnum { MyEnum_blah, MyEnum_bleh, MyEnum_bluh }; enum MyEnum val = ...; switch (val) { case MyEnum_blah: ... case MyEnum_bleh: ... case MyEnum_bluh: ... } It's not very attractive. C++ eventually added some more syntax so the members had to be qualified. This is because once the project exceeds a certain level of complexity, qualifying those enum member names becomes desirable. But if you still want unqualified names, `alias` is the feature: enum MyEnum { blah, bleh, bluh } alias blah = MyEnum.blah; alias bleh = MyEnum.bleh; alias bluh = MyEnum.bluh; `alias` is an all-purpose tool for moving names from one scope to another. Of course, one can probably do a mixin to automate the alias declarations. It should be a fun exercise. Any takers? (As mentioned by others, `with` does it too, but `with` only affects the scope it specifies.)
Jul 20 2021
On Wednesday, 21 July 2021 at 06:39:18 UTC, Walter Bright wrote: [...]But if you still want unqualified names, `alias` is the feature: enum MyEnum { blah, bleh, bluh } alias blah = MyEnum.blah; alias bleh = MyEnum.bleh; alias bluh = MyEnum.bluh;`alias` is an all-purpose tool for moving names from one scope to another. Of course, one can probably do a mixin to automate the alias declarations. It should be a fun exercise. Any takers?mixin({ auto aliasList = ""; static foreach(m; __traits(allMembers, MyEnum)) aliasList ~= "alias "~m~" = MyEnum."~m~";\n" return aliasList; }());(As mentioned by others, `with` does it too, but `with` only affects the scope it specifies.)
Jul 21 2021
On 7/21/2021 12:11 AM, Patrick Schluter wrote:Sweet! Please put in the D wiki somewhere!`alias` is an all-purpose tool for moving names from one scope to another. Of course, one can probably do a mixin to automate the alias declarations. It should be a fun exercise. Any takers?mixin({ auto aliasList = ""; static foreach(m; __traits(allMembers, MyEnum)) aliasList ~= "alias "~m~" = MyEnum."~m~";\n" return aliasList; }());
Jul 21 2021
On Wednesday, 21 July 2021 at 06:39:18 UTC, Walter Bright wrote:But if you still want unqualified names, `alias` is the feature: enum MyEnum { blah, bleh, bluh } alias blah = MyEnum.blah; alias bleh = MyEnum.bleh; alias bluh = MyEnum.bluh; `alias` is an all-purpose tool for moving names from one scope to another. Of course, one can probably do a mixin to automate the alias declarations. It should be a fun exercise. Any takers? (As mentioned by others, `with` does it too, but `with` only affects the scope it specifies.)```d enum expandEnum(EnumType, string fqnEnumType = EnumType.stringof) = (){ string expandEnum = "enum {"; foreach(m;__traits(allMembers, EnumType)) { expandEnum ~= m ~ " = " ~ fqnEnumType ~ "." ~ m ~ ","; } expandEnum ~= "}"; return expandEnum; }(); enum MyEnum { blah, bleh, bluh } mixin(expandEnum!MyEnum); auto e = blah; ```
Jul 21 2021
On 7/21/2021 12:12 AM, Mike Parker wrote:enum expandEnum(EnumType, string fqnEnumType = EnumType.stringof) = (){ string expandEnum = "enum {"; foreach(m;__traits(allMembers, EnumType)) { expandEnum ~= m ~ " = " ~ fqnEnumType ~ "." ~ m ~ ","; } expandEnum ~= "}"; return expandEnum; }(); enum MyEnum { blah, bleh, bluh } mixin(expandEnum!MyEnum); auto e = blah;You & Patrick are da men! This would make a nice bite-sized article showing off D's metaprogramming facilities.
Jul 21 2021
On Wednesday, 21 July 2021 at 07:12:25 UTC, Mike Parker wrote:```d enum expandEnum(EnumType, string fqnEnumType = EnumType.stringof) = (){Eeek, this is awful. It uses .stringof which means it is automatically stinky. It is liable for trouble when anything other than basic imports get involved. If you are going to do this kind of thing as a mixin at all, a mixin template is far more appropriate. It avoids the scope trouble since it can use the unambiguous local name. But when there's `with`.... none of this stuff gains you anything. It doesn't get closer to the Swift examples.
Jul 21 2021
On 7/21/2021 3:22 PM, Adam D Ruppe wrote:On Wednesday, 21 July 2021 at 07:12:25 UTC, Mike Parker wrote:Just use it right after the declaration of the enum.```d enum expandEnum(EnumType, string fqnEnumType = EnumType.stringof) = (){Eeek, this is awful. It uses .stringof which means it is automatically stinky. It is liable for trouble when anything other than basic imports get involved.It doesn't get closer to the Swift examples.How so?
Jul 21 2021
On Wednesday, 21 July 2021 at 23:00:06 UTC, Walter Bright wrote:Just use it right after the declaration of the enum.That limits the usefulness, but you still might as well do it right since then it works anywhere.Consider: import a; import b; foo(something); bar(something); foo and bar take different types that both have a member something. the swift examples resolve correctly. This does not and requires disambiguation on both uses.It doesn't get closer to the Swift examples.How so?
Jul 21 2021
On 7/21/2021 4:32 PM, Adam D Ruppe wrote:Consider: import a; import b; foo(something); bar(something); foo and bar take different types that both have a member something. the swift examples resolve correctly. This does not and requires disambiguation on both uses.True, but that isn't specific to enums. D does not attempt to do overloading on anything but functions & templates. Implementing russhy's proposal won't change that.
Jul 21 2021
On Tuesday, 20 July 2021 at 15:50:49 UTC, russhy wrote:So what do you think? yay? nay? why not?Personally, I have no issue with the current setup. I like knowing exactly where the enum values are coming from, and the existing tools to cut down on the typing (like with) are sufficient. But if you do want to propose a solution, I don't think `.foo` is the way to go. It looks too much like the module scope operator: https://dlang.org/spec/module.html#module_scope_operators I have no idea what that would mean for the implementation (and you'd need to account for that in the DIP), but visually it would be an unnecessary speed bump when mentally parsing the code.
Jul 20 2021
On Tuesday, 20 July 2021 at 15:50:49 UTC, russhy wrote:So what do you think? yay? nay? why not? [1] https://github.com/RUSshy/DIPs/blob/patch-2/DIPs/DIP1xxx.mdCurrently, name lookup in D is done independently from type-checking. This proposal would require name lookup to depend on type checking in order to compile code like the following example: ```d enum A { x } enum B { x } A var = .x; ``` I don't think adding this kind of complexity to the language semantics is worth it just to save a few characters.
Jul 20 2021
On Tuesday, 20 July 2021 at 16:34:13 UTC, Paul Backus wrote:On Tuesday, 20 July 2021 at 15:50:49 UTC, russhy wrote:One could argue that function overloading is a case where name resolution already depends on type checking. In a sense, `x` (in the above snippet) would be an overloaded name, which can resolved in a given context. Note that the question of overloading manifest constants was raised when the first-class function [DIP][1] was active. If that DIP is revisited, the question would need to be resolved.So what do you think? yay? nay? why not? [1] https://github.com/RUSshy/DIPs/blob/patch-2/DIPs/DIP1xxx.mdCurrently, name lookup in D is done independently from type-checking. This proposal would require name lookup to depend on type checking in order to compile code like the following example: ```d enum A { x } enum B { x } A var = .x; ```I don't think adding this kind of complexity to the language semantics is worth it just to save a few characters.I don't mind keeping D simpler, but I want to point out that the complexity depends on the scope of the feature. Function calls are likely harder to implement due to overloading, based on the comment [here][2], but target-typed variable initialization and assignment is likely more straightforward. OTOH, allowing target-typed literals in one place (variable init / assignment) and not in other (function calls) could be regarded as a pointless and artificial design limitation (similar to how struct literals are allowed only for [variable initialization][3]). * https://docs.microsoft.com/en-us/dotnet/csharp/whats-new/csharp-9#fit-and-finish-features * https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/proposals/csharp-9.0/target-typed-new [1]: https://github.com/dlang/DIPs/pull/16#discussion-diff-71641427 [2]: https://issues.dlang.org/show_bug.cgi?id=16437#c2 [3]: https://dlang.org/spec/struct#static_struct_init
Jul 21 2021
On 7/21/2021 8:13 AM, Petar Kirov [ZombineDev] wrote:similar to how struct literals are allowed only for [variable initialization][3]Struct literals can be anywhere once named parameters are implemented. They already can be if you don't need to use named parameters.
Jul 21 2021
On Wednesday, 21 July 2021 at 15:13:36 UTC, Petar Kirov [ZombineDev] wrote:OTOH, allowing target-typed literals in one place (variable init / assignment) and not in other (function calls) could be regarded as a pointless and artificial design limitation (similar to how struct literals are allowed only for [variable initialization][3]). * https://docs.microsoft.com/en-us/dotnet/csharp/whats-new/csharp-9#fit-and-finish-features * https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/proposals/csharp-9.0/target-typed-new [3]: https://dlang.org/spec/struct#static_struct_initIMO D's target-typed literals (also called "polysemous literals") are also a misfeature. They lead to weird, unintuitive situations where seemingly-equivalent code has different behavior; for example: ```d import std.stdio; void fun(double[] arr) { writeln("double"); } void fun(T)(T[] arr) { writeln(T.stringof); } void main() { fun([1, 2, 3]); auto arr = [1, 2, 3]; fun(arr); } ``` A language with fully-context-aware type inference would infer both arrays as `double[]`. A language with fully-context-independent type inference would infer both as `int[]`. In D, however, we get the worst of both worlds: type inference is *mostly* context-independent (so we have to add type annotations even in cases that are unambiguous), but there are a few special cases where context is taken into account (so we have to be mindful of context when refactoring, since a change in context could change the inferred type of an expression).
Jul 22 2021
On Thursday, 22 July 2021 at 16:41:30 UTC, Paul Backus wrote:IMO D's target-typed literals (also called "polysemous literals") are also a misfeature. They lead to weird, unintuitive situations where seemingly-equivalent code has different behavior; for example: ```d import std.stdio; void fun(double[] arr) { writeln("double"); } void fun(T)(T[] arr) { writeln(T.stringof); } void main() { fun([1, 2, 3]); auto arr = [1, 2, 3]; fun(arr); } ``` A language with fully-context-aware type inference would infer both arrays as `double[]`. A language with fully-context-independent type inference would infer both as `int[]`. In D, however, we get the worst of both worlds: type inference is *mostly* context-independent (so we have to add type annotations even in cases that are unambiguous), but there are a few special cases where context is taken into account (so we have to be mindful of context when refactoring, since a change in context could change the inferred type of an expression).It’s not so bad IMO. Type inference in D isn’t far from just “forward, one step at a time”, which is easy to understand but still very powerful.
Jul 22 2021
On Tuesday, 20 July 2021 at 15:50:49 UTC, russhy wrote:Hello I all the time wondered why we always have to be so much verbose with enum, when it's not casting to primitives, it is about repeating their long type name, constantly, all the time After trying some other languages over the past few years, i discovered in zig you can just ommit the enum type name and just use enums this way: .MY_VALUE I don't know if that's something that could be supported with D, i am not a compiler dude, so i don't have the answer Adam on discord mentioned using with(ENUM_TYPE) or just an alias, but i think we go ahead and make it simple I had prepared a DIP [1], not ready at all, but i wanted to initiate some discussion about that feature So what do you think? yay? nay? why not? [1] https://github.com/RUSshy/DIPs/blob/patch-2/DIPs/DIP1xxx.mdIn the past [I liked the idea](https://issues.dlang.org/show_bug.cgi?id=16437), so it's a _why not_ for me. From what I remember of the experiment this was not pleasant to implement. It required an array of enum declaration to be added to the internal `Scope` class.
Jul 20 2021
On Wed, Jul 21, 2021 at 1:56 AM russhy via Digitalmars-d <digitalmars-d puremagic.com> wrote:Hello I all the time wondered why we always have to be so much verbose with enum, when it's not casting to primitives, it is about repeating their long type name, constantly, all the time After trying some other languages over the past few years, i discovered in zig you can just ommit the enum type name and just use enums this way: .MY_VALUE I don't know if that's something that could be supported with D, i am not a compiler dude, so i don't have the answer Adam on discord mentioned using with(ENUM_TYPE) or just an alias, but i think we go ahead and make it simple I had prepared a DIP [1], not ready at all, but i wanted to initiate some discussion about that feature So what do you think? yay? nay? why not? [1] https://github.com/RUSshy/DIPs/blob/patch-2/DIPs/DIP1xxx.mdWhen I work in C/C++ and other similar languages, I find that on anything beyound a trivial program and particularly in a library a namespace gets baked into the variable name. When using D I find that the verbosity works out to be the same for example SDL_INIT_VIDEO becomes SDL_INIT.VIDEO and then I end up with less verbosity in a switch using with as other people have mentioned.
Jul 20 2021
On Tuesday, 20 July 2021 at 15:50:49 UTC, russhy wrote:So what do you think? yay? nay? why not? [1] https://github.com/RUSshy/DIPs/blob/patch-2/DIPs/DIP1xxx.mdThe `.` syntax is ambiguous because `.` is the module-scope operator. There's also the question of what to do with nested enums: ``` struct Foo { enum Bar { A, B, } void func () { assert(A == 0); // Should it work ? assert(.A == 0); // Or should it be this ? // The above currently refers to the `struct A`. } } struct A {} ``` The only time I had found enums to be too verbose is in switch statements. As mentioned previously, `switch (value) with `(EnumType)` helps. I think we should make it the default (essentially `case`s should be in a `with (typeof(value))` scope), and that would alleviate most of the pain.
Jul 20 2021
On 7/20/2021 8:10 PM, Mathias LANG wrote:struct Foo { enum Bar { A, B, } void func () { assert(A == 0); // Should it work ?If you want anonymous enums, use: enum { A, B }assert(.A == 0); // Or should it be this ?Then you'd have no way to access a module scope symbol with the same name.// The above currently refers to the `struct A`. } } struct A {} ``` The only time I had found enums to be too verbose is in switch statements. As mentioned previously, `switch (value) with `(EnumType)` helps.Yup.I think we should make it the default (essentially `case`s should be in a `with (typeof(value))` scope), and that would alleviate most of the pain.Sorry, I'm not understanding the pain.
Jul 20 2021
On Wednesday, 21 July 2021 at 06:19:20 UTC, Walter Bright wrote:What I meant was that instead of recommending our users to use `switch (value) with `(EnumType)`, we could just make it the default since it's the common case with enums. Unless we think that requiring the type of the enum be spelt out is better. It could add to the long list of those usability enhancements that are a hallmark of D (like `_` in number literals). I personally don't mind the verbosity, but I heard this complaint a few times over the years.The only time I had found enums to be too verbose is in switch statements. As mentioned previously, `switch (value) with `(EnumType)` helps.Yup.I think we should make it the default (essentially `case`s should be in a `with (typeof(value))` scope), and that would alleviate most of the pain.Sorry, I'm not understanding the pain.
Jul 21 2021
On 7/21/2021 8:47 PM, Mathias LANG wrote:What I meant was that instead of recommending our users to use `switch (value) with `(EnumType)`, we could just make it the default since it's the common case with enums. Unless we think that requiring the type of the enum be spelt out is better. It could add to the long list of those usability enhancements that are a hallmark of D (like `_` in number literals). I personally don't mind the verbosity, but I heard this complaint a few times over the years.Ok, I see what you mean. If it was restricted to the case value expressions, there is merit to the idea. But suppose: enum A = 3, B = 4; switch (x) { case A: ... case B: ... } there isn't much of a clue that `case A` is not `case 3`, which matters more and more the larger the program gets. One thing I've learned with D is that programmers often have mental models of how symbol lookup is done that diverge substantially from how it actually works, and I've never been able to communicate how things actually work to them. Putting a special case in like this is pretty risky.
Jul 21 2021
I can see the Scott Meyers slide on "Quirks Of D" already: "You would think that this would be `case 3`. But noooo, you'd be wrong!"
Jul 21 2021
On Thursday, 22 July 2021 at 04:37:43 UTC, Walter Bright wrote:there isn't much of a clue that `case A` is not `case 3`, which matters more and more the larger the program gets.That's a very good point, I didn't think about local enum when trying to come up with corner cases. And IMO that's a dealbreaker for this idea, since local enums for case statements aren't that rare, at least in the code I've worked with.
Jul 21 2021
On 22/07/2021 4:37 PM, Walter Bright wrote:One thing I've learned with D is that programmers often have mental models of how symbol lookup is done that diverge substantially from how it actually works, and I've never been able to communicate how things actually work to them.If you can't describe it using words, use code instead. That logic in the compiler could be a great example of your desire to distill it down. If the logic and data is encapsulated well, it could look very pseudo-code-ish!
Jul 21 2021
On 7/21/2021 11:28 PM, rikki cattermole wrote:If you can't describe it using words, use code instead.I tried everything, including that. I really cannot explain it. It was a very frustrating experience.
Jul 22 2021
On 22/07/2021 8:37 PM, Walter Bright wrote:On 7/21/2021 11:28 PM, rikki cattermole wrote:Oh hmm. I just went looking for it, the only files regarding semantic analysis I thought it could be in yup... 700 LOC method. Found that rather quickly. That really isn't a good sign I must admit!If you can't describe it using words, use code instead.I tried everything, including that. I really cannot explain it. It was a very frustrating experience.
Jul 22 2021
On 7/22/2021 3:03 AM, rikki cattermole wrote:On 22/07/2021 8:37 PM, Walter Bright wrote:The symbol lookup used to be very simple and completely consistent in D. It got a *lot* more complicated as a result of my inability to explain how it worked. It does two passes now, and is very inconsistent.On 7/21/2021 11:28 PM, rikki cattermole wrote:Oh hmm. I just went looking for it, the only files regarding semantic analysis I thought it could be in yup... 700 LOC method. Found that rather quickly. That really isn't a good sign I must admit!If you can't describe it using words, use code instead.I tried everything, including that. I really cannot explain it. It was a very frustrating experience.
Jul 22 2021
On Thursday, 22 July 2021 at 17:28:02 UTC, Walter Bright wrote:On 7/22/2021 3:03 AM, rikki cattermole wrote:You mean this isn't true anymore? https://dlang.org/spec/module.html#name_lookupOn 22/07/2021 8:37 PM, Walter Bright wrote:The symbol lookup used to be very simple and completely consistent in D. It got a *lot* more complicated as a result of my inability to explain how it worked. It does two passes now, and is very inconsistent.On 7/21/2021 11:28 PM, rikki cattermole wrote:Oh hmm. I just went looking for it, the only files regarding semantic analysis I thought it could be in yup... 700 LOC method. Found that rather quickly. That really isn't a good sign I must admit!If you can't describe it using words, use code instead.I tried everything, including that. I really cannot explain it. It was a very frustrating experience.
Jul 22 2021
On Thursday, 22 July 2021 at 04:37:43 UTC, Walter Bright wrote:On 7/21/2021 8:47 PM, Mathias LANG wrote:and I've never beenWhat I meant was that instead of recommending our users to useable to communicate how things actually work to them.Because the forum can not label the post, and We didn't sort out the `answers and posts`. So, you answer it `over and over again`. And You will be asked the same question again and again. We need to mobilize the community to submit what they think `excellent and useful` answers and label them for classify. And specially put in a section of the forum like `Good Answers and Posts`, And should add `label` function to the `posts` and `answers` for the forum.
Jul 21 2021
On Thursday, 22 July 2021 at 04:37:43 UTC, Walter Bright wrote:On 7/21/2021 8:47 PM, Mathias LANG wrote:This case is comparable to variable shadowing and should then be handled the same way. btw, as of now, what will happen in the case ``` enum ENUM { A, B, C } ENUM x = ENUM.A; enum A = 3, B = 4; switch (x) with (ENUM) { case A: writeln("case A=", cast(int)A);break; case B: writeln("case B=", cast(int)B);break; default:writeln("whatever x=", cast(int)x); } ``` https://run.dlang.io/is/7Ar7dQ it will use the values defined in ENUM and ignore the `enum A` and `enum B` values. The compiler should at least warn of the ambiguity if the `with(ENUM)` is removed.What I meant was that instead of recommending our users to use `switch (value) with `(EnumType)`, we could just make it the default since it's the common case with enums. Unless we think that requiring the type of the enum be spelt out is better. It could add to the long list of those usability enhancements that are a hallmark of D (like `_` in number literals). I personally don't mind the verbosity, but I heard this complaint a few times over the years.Ok, I see what you mean. If it was restricted to the case value expressions, there is merit to the idea. But suppose: enum A = 3, B = 4; switch (x) { case A: ... case B: ... } there isn't much of a clue that `case A` is not `case 3`, which matters more and more the larger the program gets.One thing I've learned with D is that programmers often have mental models of how symbol lookup is done that diverge substantially from how it actually works, and I've never been able to communicate how things actually work to them. Putting a special case in like this is pretty risky.
Jul 22 2021
On Thursday, 22 July 2021 at 04:37:43 UTC, Walter Bright wrote:On 7/21/2021 8:47 PM, Mathias LANG wrote:Currently, that's what happens ``` enum ENUM { A, B, C } ENUM x = ENUM.A; enum A = 3, B = 4; switch (x) /*with (ENUM)*/ { case A: writeln("case A=", cast(int)A);break; case B: writeln("case B=", cast(int)B);break; default:writeln("whatever x=", cast(int)x); } ``` onlineapp.d(11): Error: cannot implicitly convert expression `3` of type `int` to `ENUM` onlineapp.d(12): Error: cannot implicitly convert expression `4` of type `int` to `ENUM` onlineapp.d(12): Error: duplicate `case 4` in `switch` statement https://run.dlang.io/is/a12yVL The compiler will already do the right thing as it cannot convert the `enum A` and `enum B` to the type of x.What I meant was that instead of recommending our users to use `switch (value) with `(EnumType)`, we could just make it the default since it's the common case with enums. Unless we think that requiring the type of the enum be spelt out is better. It could add to the long list of those usability enhancements that are a hallmark of D (like `_` in number literals). I personally don't mind the verbosity, but I heard this complaint a few times over the years.Ok, I see what you mean. If it was restricted to the case value expressions, there is merit to the idea. But suppose: enum A = 3, B = 4; switch (x) { case A: ... case B: ... } there isn't much of a clue that `case A` is not `case 3`, which matters more and more the larger the program gets.One thing I've learned with D is that programmers often have mental models of how symbol lookup is done that diverge substantially from how it actually works, and I've never been able to communicate how things actually work to them. Putting a special case in like this is pretty risky.
Jul 22 2021
On Thursday, 22 July 2021 at 07:42:33 UTC, Patrick Schluter wrote:https://run.dlang.io/is/a12yVL The compiler will already do the right thing as it cannot convert the `enum A` and `enum B` to the type of x.Sorry for the massive disapointment but it can : https://run.dlang.io/is/ktKQPT.
Jul 22 2021
On Thursday, 22 July 2021 at 07:49:23 UTC, Basile B. wrote:On Thursday, 22 July 2021 at 07:42:33 UTC, Patrick Schluter wrote:Sometimes i think the main problem with D is all these weird corner cases pop up and people dont say oh look we need to fix this, nail it down, make it consistent, they say or look cool a new feature! Not directed at you fwiw.https://run.dlang.io/is/a12yVL The compiler will already do the right thing as it cannot convert the `enum A` and `enum B` to the type of x.Sorry for the massive disapointment but it can : https://run.dlang.io/is/ktKQPT.
Jul 22 2021
On 7/22/2021 1:37 AM, claptrap wrote:Sometimes i think the main problem with D is all these weird corner cases pop up and people dont say oh look we need to fix this, nail it down, make it consistent, they say or look cool a new feature!Programming languages aren't completely consistent because: 1. people don't want them to be 2. what the software must interact with isn't consistent 3. the CPU is not consistent This whole thread is about adding an inconsistent feature.
Jul 22 2021
On Thursday, 22 July 2021 at 07:49:23 UTC, Basile B. wrote:On Thursday, 22 July 2021 at 07:42:33 UTC, Patrick Schluter wrote:```d - enum ENUM { A, B, C } + enum ENUM : ubyte { A, B, C } ``` You should have put your change also on the forum so that everyone can see. Yes, that's indeed a problem but IMHO it's a bug due to int promotion rule.https://run.dlang.io/is/a12yVL The compiler will already do the right thing as it cannot convert the `enum A` and `enum B` to the type of x.Sorry for the massive disapointment but it can : https://run.dlang.io/is/ktKQPT.
Jul 22 2021
On Thursday, 22 July 2021 at 08:41:55 UTC, Patrick Schluter wrote:On Thursday, 22 July 2021 at 07:49:23 UTC, Basile B. wrote: Yes, that's indeed a problem but IMHO it's a bug due to int promotion rule.Its not a bug it's a feature!
Jul 22 2021
On Thursday, 22 July 2021 at 08:41:55 UTC, Patrick Schluter wrote:On Thursday, 22 July 2021 at 07:49:23 UTC, Basile B. wrote:Yes it is definitively a bug, I know it already but I could not resist to recall to the community that it exists, as your example matched _perfectly_. sorry ;)On Thursday, 22 July 2021 at 07:42:33 UTC, Patrick Schluter wrote:```d - enum ENUM { A, B, C } + enum ENUM : ubyte { A, B, C } ``` You should have put your change also on the forum so that everyone can see. Yes, that's indeed a problem but IMHO it's a bug due to int promotion rule.https://run.dlang.io/is/a12yVL The compiler will already do the right thing as it cannot convert the `enum A` and `enum B` to the type of x.Sorry for the massive disapointment but it can : https://run.dlang.io/is/ktKQPT.
Jul 22 2021
On Thursday, 22 July 2021 at 08:51:12 UTC, Basile B. wrote:On Thursday, 22 July 2021 at 08:41:55 UTC, Patrick Schluter wrote:Don't be sorry when what you say is true. :-)On Thursday, 22 July 2021 at 07:49:23 UTC, Basile B. wrote:Yes it is definitively a bug, I know it already but I could not resist to recall to the community that it exists, as your example matched _perfectly_. sorry ;)On Thursday, 22 July 2021 at 07:42:33 UTC, Patrick Schluter wrote:```d - enum ENUM { A, B, C } + enum ENUM : ubyte { A, B, C } ``` You should have put your change also on the forum so that everyone can see. Yes, that's indeed a problem but IMHO it's a bug due to int promotion rule.[...]Sorry for the massive disapointment but it can : https://run.dlang.io/is/ktKQPT.
Jul 22 2021
On Thursday, 22 July 2021 at 08:51:12 UTC, Basile B. wrote:On Thursday, 22 July 2021 at 08:41:55 UTC, Patrick Schluterbugzilla: https://issues.dlang.org/show_bug.cgi?id=6226 https://issues.dlang.org/show_bug.cgi?id=21460Yes, that's indeed a problem but IMHO it's a bug due to int promotion rule.Yes it is definitively a bug, I know it already but I could not resist to recall to the community that it exists, as your example matched _perfectly_. sorry ;)
Jul 22 2021
On Tuesday, 20 July 2021 at 15:50:49 UTC, russhy wrote:HelloAnd the default constructor, Why can't it like `C++`: `T t;` That's all. Many C++ programmers want to have constructors like `C++` as `T t{...};`.
Jul 20 2021
On Wednesday, 21 July 2021 at 06:12:20 UTC, zjh wrote:On Tuesday, 20 July 2021 at 15:50:49 UTC, russhy wrote:yes that too.. if you can create DIP draft for it and post it on the forum too? se we can have discussion about that tooHelloAnd the default constructor, Why can't it like `C++`: `T t;` That's all. Many C++ programmers want to have constructors like `C++` as `T t{...};`.
Jul 21 2021
On 7/21/2021 12:08 PM, russhy wrote:On Wednesday, 21 July 2021 at 06:12:20 UTC, zjh wrote:It's been discussed many times. It comes up once a year or so.On Tuesday, 20 July 2021 at 15:50:49 UTC, russhy wrote:yes that too.. if you can create DIP draft for it and post it on the forum too? se we can have discussion about that tooHelloAnd the default constructor, Why can't it like `C++`: `T t;` That's all. Many C++ programmers want to have constructors like `C++` as `T t{...};`.
Jul 21 2021
On Wednesday, 21 July 2021 at 21:04:56 UTC, Walter Bright wrote:On 7/21/2021 12:08 PM, russhy wrote:And the default constructor, Why can't it like `C++`: `T t;` That's all. Many C++ programmers want to have constructors like `C++` as `T t{...};`.It's been discussed many times. It comes up once a year or so.I really don't understand. Isn't `d` called `pragmatism`? That's so much a little bit of improvement, d can attract a bunch of c++ people, and I don't know `why not to do it`? Some people say that when using `d`, the friction force is small. Since this is an advantage, why not `strengthen` it? For the so-called `consistency`? Are you not against what is called `consistency`?
Jul 21 2021
On Thursday, 22 July 2021 at 01:12:40 UTC, zjh wrote:On Wednesday, 21 July 2021 at 21:04:56 UTC, Walter Bright wrote:Initialization in C++ is described as a "nightmare" by experienced C++ programmers [1]. This is probably not something that D would benefit from imitating. [1] https://www.youtube.com/watch?v=7DTlWPgX6zsOn 7/21/2021 12:08 PM, russhy wrote:And the default constructor, Why can't it like `C++`: `T t;` That's all. Many C++ programmers want to have constructors like `C++` as `T t{...};`.It's been discussed many times. It comes up once a year or so.I really don't understand. Isn't `d` called `pragmatism`? That's so much a little bit of improvement, d can attract a bunch of c++ people, and I don't know `why not to do it`? Some people say that when using `d`, the friction force is small. Since this is an advantage, why not `strengthen` it? For the so-called `consistency`? Are you not against what is called `consistency`?
Jul 21 2021
On Thursday, 22 July 2021 at 01:40:07 UTC, Paul Backus wrote:On Thursday, 22 July 2021 at 01:12:40 UTC, zjh wrote:I am also `experienced ` C++ Programmer,why I don't hurt from it?On Wednesday, 21 July 2021 at 21:04:56 UTC, Walter Bright
Jul 21 2021
On 7/21/2021 7:12 PM, zjh wrote:I am also `experienced ` C++ Programmer,why I don't hurt from it?There are many ways to experience C++. Anyhow, the reason that default constructors are not allowed is so that default constructing an object will always succeed. This makes for a significant reduction in complexity. For example, default construction then becomes pure and nothrow. Not everyone agrees, of course.
Jul 21 2021
On Thursday, 22 July 2021 at 04:26:45 UTC, Walter Bright wrote:On 7/21/2021 7:12 PM, zjh wrote:As a `plain user`, I hope to have the same convenience as `C++`. I know you are very professional. But, the development of `the D language`,Don't you need a lot of `primary users`? IMO, As a language leader, You should provide users with a variety of choices like `C++`. When users feel great, they will naturally let their friends to use `D`. `C++'s` advantage is although It don't do well, but It provide you basic facilities. `D`,the biggest weakness is ecology. Ecology is made up of users. A large number of users may not be as professional as you. So I think `d` should work hard on `small details` to gain users. I've been saying that the biggest advantage of D is `better c++`, which can attract `C++ programmers`. `C++ programmer`, can help `D` in two places, one is to bring the user, the other is to bring the library which brings the user. Therefore, D should pay more attention to the experience of the `C++ man`, rather than the average force, resulting in nothing.I am also `experienced ` C++ Programmer,why I don't hurt from it?
Jul 21 2021
On Thursday, 22 July 2021 at 06:12:43 UTC, zjh wrote:On Thursday, 22 July 2021 at 04:26:45 UTC, Walter Bright wrote:Primary users increase, promote the increase of lib writers, increase users, and increase lib writers. Why more users, more people write library, because more people use, more sense of achievement. More libraries, naturally increase users. So the more users, the better. The more users, the more errors found, the more errors corrected, the better experience, and the more users. In this way, it also constitutes a positive cycle. Therefore, we must pay attention to `primary users`.On 7/21/2021 7:12 PM, zjh wrote:I am also `experienced ` C++ Programmer,why I don't hurt from it?
Jul 21 2021
On 7/21/2021 11:12 PM, zjh wrote:As a `plain user`, I hope to have the same convenience as `C++`. I know you are very professional. But, the development of `the D language`,Don't you need a lot of `primary users`? IMO, As a language leader, You should provide users with a variety of choices like `C++`. When users feel great, they will naturally let their friends to use `D`. `C++'s` advantage is although It don't do well, but It provide you basic facilities. `D`,the biggest weakness is ecology. Ecology is made up of users. A large number of users may not be as professional as you. So I think `d` should work hard on `small details` to gain users. I've been saying that the biggest advantage of D is `better c++`, which can attract `C++ programmers`. `C++ programmer`, can help `D` in two places, one is to bring the user, the other is to bring the library which brings the user. Therefore, D should pay more attention to the experience of the `C++ man`, rather than the average force, resulting in nothing.One of D's goals is to not have C++ features that cause more problems than they are worth. Of course, this is a judgement call and people have different opinions about it. It's also pretty clear that every feature C++ has, good or bad, has its adherents and champions.
Jul 22 2021
On 7/20/21 11:50 AM, russhy wrote:Hello I all the time wondered why we always have to be so much verbose with enum, when it's not casting to primitives, it is about repeating their long type name, constantly, all the time After trying some other languages over the past few years, i discovered in zig you can just ommit the enum type name and just use enums this way: .MY_VALUE I don't know if that's something that could be supported with D, i am not a compiler dude, so i don't have the answer Adam on discord mentioned using with(ENUM_TYPE) or just an alias, but i think we go ahead and make it simple I had prepared a DIP [1], not ready at all, but i wanted to initiate some discussion about that feature So what do you think? yay? nay? why not? [1] https://github.com/RUSshy/DIPs/blob/patch-2/DIPs/DIP1xxx.mdI enjoy having this type of shortcut in Swift, and wish D had something similar. To give some perspective, look no further than configuration options of std.algorithm: ```d arr.sort!("a < b", .unstable); // instead of SwapStrategy.unstable ``` Clear as the original, and less verbose. In Swift, enums are used extensively, and I don't think they would be if the shortcut syntax wasn't available. And in general, any function parameter enums are cumbersome to write in D. However, using `.enumMember` isn't viable as noted by several people. If I were to propose something, it would be to have a short substitute expression type to lookup the member. Then you can do things like type. It wouldn't be a panacea though, since overloading would make this ambiguous. But assignment/initialization would be unambiguous. Probably not going to fly in D. -Steve
Jul 21 2021
On Wednesday, 21 July 2021 at 13:36:37 UTC, Steven Schveighoffer wrote:On 7/20/21 11:50 AM, russhy wrote:of course the . syntax isn't final, the point of the DIP discussion was to discuss about the ability to omit the enum type name, the syntax can always be something elseHello I all the time wondered why we always have to be so much verbose with enum, when it's not casting to primitives, it is about repeating their long type name, constantly, all the time After trying some other languages over the past few years, i discovered in zig you can just ommit the enum type name and just use enums this way: .MY_VALUE I don't know if that's something that could be supported with D, i am not a compiler dude, so i don't have the answer Adam on discord mentioned using with(ENUM_TYPE) or just an alias, but i think we go ahead and make it simple I had prepared a DIP [1], not ready at all, but i wanted to initiate some discussion about that feature So what do you think? yay? nay? why not? [1] https://github.com/RUSshy/DIPs/blob/patch-2/DIPs/DIP1xxx.mdI enjoy having this type of shortcut in Swift, and wish D had something similar. To give some perspective, look no further than configuration options of std.algorithm: ```d arr.sort!("a < b", .unstable); // instead of SwapStrategy.unstable ``` Clear as the original, and less verbose. In Swift, enums are used extensively, and I don't think they would be if the shortcut syntax wasn't available. And in general, any function parameter enums are cumbersome to write in D. However, using `.enumMember` isn't viable as noted by several people. If I were to propose something, it would be to have a short then uses the expression type to lookup the member. Then you return an instance of the type. It wouldn't be a panacea though, since overloading would make this ambiguous. But assignment/initialization would be unambiguous. Probably not going to fly in D. -Steve
Jul 21 2021
of course the . syntax isn't final, the point of the DIP discussion was to discuss about the ability to omit the enum type name, the syntax can always be something else edit: quoting is kind hard to follow in the text editor here, i made a mistake on the reply above by typing inside the quote
Jul 21 2021
On 7/21/2021 6:36 AM, Steven Schveighoffer wrote:I enjoy having this type of shortcut in Swift, and wish D had something similar.Your wish has been heard and duly granted. The internet delivers once again! See Patrick Schluter and Mike Parker's solutions upthread.
Jul 21 2021
On 7/21/21 5:02 PM, Walter Bright wrote:On 7/21/2021 6:36 AM, Steven Schveighoffer wrote:No, `mixin something; thenCallFunction(...);` isn't even close to the same. -SteveI enjoy having this type of shortcut in Swift, and wish D had something similar.Your wish has been heard and duly granted. The internet delivers once again! See Patrick Schluter and Mike Parker's solutions upthread.
Jul 21 2021
On 7/21/2021 2:16 PM, Steven Schveighoffer wrote:No, `mixin something; thenCallFunction(...);` isn't even close to the same.I don't know what it is you're asking for, then.
Jul 21 2021
On 7/21/21 7:59 PM, Walter Bright wrote:On 7/21/2021 2:16 PM, Steven Schveighoffer wrote:I'm not asking for anything. What I'm saying is the feature in Swift (called "dot syntax") that allows one to use `.enumMember` wherever a specific enum is required, is not the same as creating symbol aliases for all the enum members in your namespace (or in module namespace). The Swift feature is contextual based on the expression *type*, and doesn't require any extra machinery around it. This means that you don't have weird ambiguities when you have multiple enums as parameters, or names that are local that might override the names. e.g.: ```d enum A { one, two, three } enum B { one, two, three } void foo(A a, B b) {... } // how to call foo without having to specify `A.one` or `B.one`? ``` In Swift, `.symbol` is specifically for type properties, and fit perfectly for enums (and other things, see [here](https://www.swiftbysundell.com/tips/using-dot-syntax-for-static-properties- nd-initializers/)). It does not have the meaning that D has, so it can get away with this. I don't expect D to implement such a thing, and yes, you can do mixin hacks or `with` statements (though there are drawbacks to both). Just saying `.member` instead of `FullEnumType.member` whenever a `FullEnumType` is required is a nice feature of Swift, and I would like to see something like it in D, but I can live without it. BUT if it were to be implemented, obviously `.symbol` doesn't work. That's why I proposed a shortcut to mean "property of the required type" such as -SteveNo, `mixin something; thenCallFunction(...);` isn't even close to the same.I don't know what it is you're asking for, then.
Jul 22 2021
On 7/22/2021 9:16 AM, Steven Schveighoffer wrote:```d enum A { one, two, three } enum B { one, two, three } void foo(A a, B b) {... } // how to call foo without having to specify `A.one` or `B.one`? ``` In Swift, `.symbol` is specifically for type properties, and fit perfectly for enums (and other things, see [here](https://www.swiftbysundell.com/tips/using-dot-syntax-for-static-properties- nd-initializers/)).How does that interact with function overloading? I looked at the Swift reference manual https://docs.swift.org/swift-book/ReferenceManual/Expressions.html and couldn't find answers there. Seems to me there'd be a combinatorial explosion as the resolver will have to re-run the match for all different resolutions for `.identifier`. Even if the compiler does try them all and find a best match, for the user reading the code I doubt it would be straightforward to figure out manually which is the right match. It's already hard enough. With the alias mixin proposed, the answer is simple. Two different enums in the same scope with the same member names will cause a compile time error.
Jul 22 2021
On 7/22/21 1:19 PM, Walter Bright wrote:On 7/22/2021 9:16 AM, Steven Schveighoffer wrote:Swift is known for "giving up" on expression inference, so possibly it could lead there. But note that Swift (and objective C) have significant parameter names, which means in many cases you *must* name the parameters when calling. This helps with overloading quite a bit (in fact, in Objective C there was no overloading, as the parameter names were part of the function name). Which is to say, the situation in Swift is definitely different than the situation in D. Overloads are handled differently, and expectations are significantly different. I tried out some stuff: ```swift import Foundation enum Foo { case a case b case c } enum Bar { case a case b } func test(_ : Foo) { print("test a"); } func test(_ : Bar) { print("test b"); } test(.a) // error, ambiguous test(Foo.a) // test a test(Bar.a) // test b test(.c) // test a ``` So it seems to work as one might expect. Since `.c` can only match the first, it's used.```d enum A { one, two, three } enum B { one, two, three } void foo(A a, B b) {... } // how to call foo without having to specify `A.one` or `B.one`? ``` In Swift, `.symbol` is specifically for type properties, and fit perfectly for enums (and other things, see [here](https://www.swiftbysundell.com/tips/using-dot-syntax-for-static-properties- nd-initializers/)).How does that interact with function overloading?I looked at the Swift reference manual https://docs.swift.org/swift-book/ReferenceManual/Expressions.html and couldn't find answers there. Seems to me there'd be a combinatorial explosion as the resolver will have to re-run the match for all different resolutions for `.identifier`.But what is "all" resolutions? A combinatorial explosion of 1 or 2 possibilities isn't bad. Remember, the symbol lookup *requires* a contextual type. For example: ```swift var x = .identifier // Compiler error, no type, even if only one type in scope has a member `identifier` var y : SomeEnum = .identifier // OK var z : SomeEnum z = .identifer // OK, we infer the meaning from the type of z ``` I know D doesn't do this. But it's also not the same as what you are saying.Even if the compiler does try them all and find a best match, for the user reading the code I doubt it would be straightforward to figure out manually which is the right match. It's already hard enough.The identifier comes from the expression target's inferred type. There are still ambiguous cases, where the compiler is going to give up. But the lookup doesn't involve the whole world either. Before you go on arguing that D doesn't do this, and shouldn't, I know. It's not that I'm trying to convince you that it should, I'm just showing what has been requested and how it differs from the "mixin solution".With the alias mixin proposed, the answer is simple. Two different enums in the same scope with the same member names will cause a compile time error.The answer is, there is no shortcut, just type out the full enum names. With Swift you do not need to. -Steve
Jul 22 2021
On 7/22/2021 11:16 AM, Steven Schveighoffer wrote:But what is "all" resolutions? A combinatorial explosion of 1 or 2 possibilities isn't bad. Remember, the symbol lookup *requires* a contextual type. For example:So it appears that Swift simply gives an error if there's more than one result for .identifier, rather than trying to find a match that fits into the context.```swift var x = .identifier // Compiler error, no type, even if only one type in scope has a member `identifier` var y : SomeEnum = .identifier // OK var z : SomeEnum z = .identifer // OK, we infer the meaning from the type of z ```Are you sure that's how Swift works? Inferring the type of the rvalue from the lvalue? Problems come from that, as in: z = x + y + .identifier; For the rvalue, this becomes "top down" type inference, as opposed to the usual "bottom up" type inference. D is exclusively "bottom up", as it is much simpler.It's not that I'm trying to convince you that it should, I'm just showing what has been requested and how it differs from the "mixin solution".Thanks!
Jul 22 2021
On Friday, 23 July 2021 at 01:09:31 UTC, Walter Bright wrote:Are you sure that's how Swift works? Inferring the type of the rvalue from the lvalue? Problems come from that, as in: z = x + y + .identifier; For the rvalue, this becomes "top down" type inference, as opposed to the usual "bottom up" type inference. D is exclusively "bottom up", as it is much simpler.It could work with bottom-up inference only. It would work the same way as `null` did before adding the bottom type: `.identifier` would be a literal of an internal compiler type, let's call it `EnumLiteral!"identifier"`. Values of that internal compiler type would implicitly convert to any enumerated type that defines `identifier`.
Jul 23 2021
On Friday, 23 July 2021 at 01:09:31 UTC, Walter Bright wrote:For the rvalue, this becomes "top down" type inference, as opposed to the usual "bottom up" type inference. D is exclusively "bottom up", as it is much simpler.D is mostly "bottom up", but there are a few corner cases [1] where it isn't, and they can lead to some very confusing errors [2]. It would probably be too disruptive to deprecate existing instances of "top down" type inference in D, but we can at least avoid adding new ones. [1] https://forum.dlang.org/post/mnxksewxtrwlxeaazvwe forum.dlang.org [2] https://forum.dlang.org/thread/xkgpheuhohbffzgdbqhb forum.dlang.org
Jul 23 2021
On Friday, 23 July 2021 at 01:09:31 UTC, Walter Bright wrote:Are you sure that's how Swift works? Inferring the type of the rvalue from the lvalue? Problems come from that, as in: z = x + y + .identifier; For the rvalue, this becomes "top down" type inference, as opposed to the usual "bottom up" type inference. D is exclusively "bottom up", as it is much simpler.I don't disagree. I think in your example here, it's not inferring the requested type from z, but would be from the operator overload function. There are two requirements here: 1. The type is inferred before the property is looked up (or at least, the set of possible types). Nearly everything in Swift is inferred type. 2. The `.identifier` is a self-producing property based on the contextual type. That is, it is a property on the expected/inferred type, AND it produces an instance of the type. It helps to remember also that Swift's enums are much more configurable than D's enums -- they are actual enumerations, and allow you to define properties, operators, etc. They are basically a specialized struct (so for instance, you can identify whether math is usable on them). -Steve
Jul 23 2021
On Tuesday, 20 July 2021 at 15:50:49 UTC, russhy wrote:So what do you think? yay? nay? why not?As mentioned by others, `enumVar = .memberName` is ambiguous with the module scope operator. If you want to pursue this, might I recommend `enumVar = "memberName"` instead? You still need no new syntax, and it could be implemented with value range propagation mechanics. This way: If a `string`, `wstring` or `dstring` `str` that is known at compile time, is assigned to value of enumerated type `ET`, it is interpreted as assigning `mixin("ET." ~ str)` to the assignee value.
Jul 21 2021
On Thursday, 22 July 2021 at 03:21:06 UTC, Dukc wrote:On Tuesday, 20 July 2021 at 15:50:49 UTC, russhy wrote:```d enum E : string { x = "y", y = "x" } E e = "y"; // what happens here? ```So what do you think? yay? nay? why not?As mentioned by others, `enumVar = .memberName` is ambiguous with the module scope operator. If you want to pursue this, might I recommend `enumVar = "memberName"` instead? You still need no new syntax, and it could be implemented with value range propagation mechanics. This way: If a `string`, `wstring` or `dstring` `str` that is known at compile time, is assigned to value of enumerated type `ET`, it is interpreted as assigning `mixin("ET." ~ str)` to the assignee value.
Jul 21 2021
On Thursday, 22 July 2021 at 03:28:44 UTC, Paul Backus wrote:```d enum E : string { x = "y", y = "x" } E e = "y"; // what happens here? ```The VRP mechanics do not currently let that compile, so nothing will break. it would be equal to `E e = E.y`; `E e = cast(E)"y"` on the other hand would still be `E e = E.x`, as it's now. Now, I admit that difference between implicit and explicit cast is confusing and a weakness. Maybe the syntax should be `E e = ".y"` instead to avoid the difference in behaviour between implicit and explicit cast.
Jul 22 2021
On Thursday, 22 July 2021 at 14:05:53 UTC, Dukc wrote:On Thursday, 22 July 2021 at 03:28:44 UTC, Paul Backus wrote:Ok, now imagine you're new to D and don't know about this feature. What are you going to *think* `E e = ".y"` does? Using string-literal syntax for things that aren't actually string literals is just asking for confusion.```d enum E : string { x = "y", y = "x" } E e = "y"; // what happens here? ```The VRP mechanics do not currently let that compile, so nothing will break. it would be equal to `E e = E.y`; `E e = cast(E)"y"` on the other hand would still be `E e = E.x`, as it's now. Now, I admit that difference between implicit and explicit cast is confusing and a weakness. Maybe the syntax should be `E e = ".y"` instead to avoid the difference in behaviour between implicit and explicit cast.
Jul 22 2021
On Thursday, 22 July 2021 at 14:58:12 UTC, Paul Backus wrote:Ok, now imagine you're new to D and don't know about this feature. What are you going to *think* `E e = ".y"` does?There would be a risk that I'd think that it's the same as `E e = .y`. Not that likely though - I may well know that E has a member y, and I could also reason that `".y"` meaning `.y` would make no sense since one could just write `.y` directly. I think you're worried about the case where I don't know that `E` is an enumerated type. In that case I could mistake `E` being some sort of string type. On the other hand, I could not fully trust that conclusion anyway, since it could also be some custom `struct` or `union` that can be initialized that way.Using string-literal syntax for things that aren't actually string literals is just asking for confusion.To some degree yes. But perhaps it's still better than new syntax.
Jul 22 2021
On Thursday, 22 July 2021 at 14:58:12 UTC, Paul Backus wrote:Ok, now imagine you're new to D and don't know about this feature. What are you going to *think* `E e = ".y"` does?Oh, I just realized adding the dot solves nothing. ```d enum E : string { x = ".y", y = ".x" } E e = ".y"; // *Facepalm* ```
Jul 22 2021
On Tuesday, 20 July 2021 at 15:50:49 UTC, russhy wrote:Hello I all the time wondered why we always have to be so much verbose with enum, when it's not casting to primitives, it is about repeating their long type name, constantly, all the time After trying some other languages over the past few years, i discovered in zig you can just ommit the enum type name and just use enums this way: .MY_VALUE I don't know if that's something that could be supported with D, i am not a compiler dude, so i don't have the answer Adam on discord mentioned using with(ENUM_TYPE) or just an alias, but i think we go ahead and make it simple I had prepared a DIP [1], not ready at all, but i wanted to initiate some discussion about that feature So what do you think? yay? nay? why not? [1] https://github.com/RUSshy/DIPs/blob/patch-2/DIPs/DIP1xxx.mdTerrible, just terrible.
Jul 22 2021