digitalmars.D - enum behaivor. another rehash of the topic
- Joseph Rice (110/110) Dec 14 2013 While I must first Admit I'm new to D. However; I have been a
- Marco Leise (21/130) Dec 14 2013
- bearophile (33/52) Dec 14 2013 This is how you usually write that code in D:
- monarch_dodra (7/8) Dec 15 2013 I've been in enough large scale C++ projects to enjoy D's verbose
- deadalnix (4/12) Dec 15 2013 Resulting in people giving name like TestT1, TestT2 as enum
- monarch_dodra (16/19) Dec 15 2013 I've usually seen the "namespace" or "struct "approach, eg:
- Tommi (14/33) Dec 15 2013 I'd rather do this:
- monarch_dodra (9/22) Dec 15 2013 That's a C++11 extension. "CheckerBoardColor::Red" is not a legal
- bearophile (17/23) Dec 15 2013 By the way, I am not criticizing "D verbose approach". I have
- monarch_dodra (23/39) Dec 15 2013 Hum... Well, it's not actually weak typing. It's strong typing
- Tommi (3/11) Dec 15 2013 A related discussion:
- Maxim Fomin (7/23) Dec 15 2013 This is not a weak typing. An example of weak typing is array
- Paulo Pinto (7/110) Dec 15 2013 It follows the same approach as many other modern languages, even C++
- Iain Buclaw (7/9) Dec 15 2013 You are in for a shock when you hear about C++11
While I must first Admit I'm new to D. However; I have been a C/C++ programmer for 15 years. I am excited about D. One of the features I love is being able to access my legacy code. But there are some cases were a complete re-write/re-factor to D makes sense. I've come to it very frustrating code that has been stable for years now needs to be changed because of a language quirk. The main selling point about D is C/C++ is almost the same syntax, I see potential in D to replace C/C++. I've noticed that enum behavior is dramatically different. This is my opinion, but I see this as a flaw in D. Again let me repeat, My opinion. While I understand D's approach to enum's. It is a hard pill to swallow for an experienced programmer. The D compiler should know the type of the enum from the symbol. You should not have to type the NAME.element when doing a comparison or assignment. Declaring an enum FOO { one, two, three} should be the same as declaring a new type. So that when you declare `FOO bar;` in code, assignment and comparison of `bar` should know what bar is comprised of because it is of type enum FOO. Therefore anything of type enum FOO can only comprise of the values 'one', 'two', or 'three'. I've prepared 3 examples, a C, C++, and Finally D. All essentially the same code. You will notice that the D version, has some vast differences. For example you can not define an enum and declare the variable all at once. This gets me to the annoying part. assigning and Comparing. jrice Wayland:~/prj/enum_example$ gcc -o enum_c enum.c jrice Wayland:~/prj/enum_example$ g++ -o enum_cpp enum.cpp jrice Wayland:~/prj/enum_example$ dmd enum.d jrice Wayland:~/prj/enum_example$ ./enum_c It's test1 jrice Wayland:~/prj/enum_example$ ./enum_cpp It's test1 jrice Wayland:~/prj/enum_example$ ./enum It's test1 jrice Wayland:~/prj/enum_example$ cat enum.c #include <stdio.h> void main() { enum TEST { test1=0, test2 } test; test = test1; switch (test) { case test1: printf("It's test1\n"); break; case test2: printf("It's test2\n"); break; default: break; } } jrice Wayland:~/prj/enum_example$ cat enum.cpp #include <iostream> using namespace std; int main() { enum TEST { test1=0, test2 } test; test = test1; switch (test) { case test1: cout << "It's test1" << endl; break; case test2: cout << "It's test2" << endl; break; default: break; } return 0; } jrice Wayland:~/prj/enum_example$ cat enum.d import std.stdio; void main() { enum TEST { test1=0, test2 }; TEST test = TEST.test1; switch (test) { case TEST.test1: writeln("It's test1"); break; case TEST.test2: writeln("It's test2"); break; default: break; } } So as you can see, D is just awkward, and it becomes tedious especially if you have many many many values in the enum. So D language Designers and maintainers: 1st I understand your reasons, it makes it un-ambiguous, becaause you know exactly which enum `test1` belongs too. 2nd What the heck, why do I have to type extra. It makes porting a little mre frustrating, and makes me question using D in the first place. 3rd I'm Pleading to you to consider making both syntax's valid. The Old C/C++ way, and the D way. If you have too, make compiler flag.
Dec 14 2013
Am Sun, 15 Dec 2013 02:16:39 +0100 schrieb "Joseph Rice" <ricejm01 gmail.com>:While I must first Admit I'm new to D. However; I have been a C/C++ programmer for 15 years. I am excited about D. One of the features I love is being able to access my legacy code. But there are some cases were a complete re-write/re-factor to D makes sense. I've come to it very frustrating code that has been stable for years now needs to be changed because of a language quirk. The main selling point about D is C/C++ is almost the same syntax, I see potential in D to replace C/C++. I've noticed that enum behavior is dramatically different. This is my opinion, but I see this as a flaw in D. Again let me repeat, My opinion. While I understand D's approach to enum's. It is a hard pill to swallow for an experienced programmer. The D compiler should know the type of the enum from the symbol. You should not have to type the NAME.element when doing a comparison or assignment. Declaring an enum FOO { one, two, three} should be the same as declaring a new type. So that when you declare `FOO bar;` in code, assignment and comparison of `bar` should know what bar is comprised of because it is of type enum FOO. Therefore anything of type enum FOO can only comprise of the values 'one', 'two', or 'three'. I've prepared 3 examples, a C, C++, and Finally D. All essentially the same code. You will notice that the D version, has some vast differences. For example you can not define an enum and declare the variable all at once. This gets me to the annoying part. assigning and Comparing. jrice Wayland:~/prj/enum_example$ gcc -o enum_c enum.c jrice Wayland:~/prj/enum_example$ g++ -o enum_cpp enum.cpp jrice Wayland:~/prj/enum_example$ dmd enum.d jrice Wayland:~/prj/enum_example$ ./enum_c It's test1 jrice Wayland:~/prj/enum_example$ ./enum_cpp It's test1 jrice Wayland:~/prj/enum_example$ ./enum It's test1 jrice Wayland:~/prj/enum_example$ cat enum.c #include <stdio.h> void main() { enum TEST { test1=0, test2 } test; test = test1; switch (test) { case test1: printf("It's test1\n"); break; case test2: printf("It's test2\n"); break; default: break; } } jrice Wayland:~/prj/enum_example$ cat enum.cpp #include <iostream> using namespace std; int main() { enum TEST { test1=0, test2 } test; test = test1; switch (test) { case test1: cout << "It's test1" << endl; break; case test2: cout << "It's test2" << endl; break; default: break; } return 0; } jrice Wayland:~/prj/enum_example$ cat enum.d import std.stdio; void main() { enum TEST { test1=0, test2 }; TEST test = TEST.test1; switch (test) { case TEST.test1: writeln("It's test1"); break; case TEST.test2: writeln("It's test2"); break; default: break; } } So as you can see, D is just awkward, and it becomes tedious especially if you have many many many values in the enum.void main() { enum TEST { test1, test2 } TEST test = TEST.test1; with(TEST) final switch (test) { case test1: writeln("It's test1"); break; case test2: writeln("It's test2"); break; } } -- Marco
Dec 14 2013
Joseph Rice:import std.stdio; void main() { enum TEST { test1=0, test2 }; TEST test = TEST.test1; switch (test) { case TEST.test1: writeln("It's test1"); break; case TEST.test2: writeln("It's test2"); break; default: break; } }This is how you usually write that code in D: void main() { import std.stdio; enum Test { t1, t2 } auto test = Test.t1; final switch (test) with (Test) { case t1: writeln("It's t1"); break; case t2: writeln("It's t2"); break; } } The differences: - The import is often better in the function. - Type names (like Test) are better written with just the first letter uppercase. - You often have to carry the type name around, so using shorter names is sometimes OK (like t1 and t2). - In this code you want a final switch. - Using with() you avoid repeating the enum type name. In D you also have anonymous enums: enum { test1, test2 } Also, when you refer to C++, it's better to use the "enum class" of C++11. D enums have some faults, like being weakly typed, having bad error messages, and sometimes being a bit too much long to write (when you pass an enum to a function, the function already knows the name of the enum type. But this is not so bad...). Bye, bearophile
Dec 14 2013
On Sunday, 15 December 2013 at 01:52:01 UTC, bearophile wrote:D enums have some faults...I've been in enough large scale C++ projects to enjoy D's verbose approach. Sure, C++ is convenient and works 99% of the time. But all you need is for some retard to create a Global enum containing things like the words "Yes, No, True, False, Red, Black, White", and then he's ruined it for *everyone* on the project.
Dec 15 2013
On Sunday, 15 December 2013 at 08:29:59 UTC, monarch_dodra wrote:On Sunday, 15 December 2013 at 01:52:01 UTC, bearophile wrote:Resulting in people giving name like TestT1, TestT2 as enum values in C++. As a result, you end up with the same verbosity as in D, without the possibility of using 'with'.D enums have some faults...I've been in enough large scale C++ projects to enjoy D's verbose approach. Sure, C++ is convenient and works 99% of the time. But all you need is for some retard to create a Global enum containing things like the words "Yes, No, True, False, Red, Black, White", and then he's ruined it for *everyone* on the project.
Dec 15 2013
On Sunday, 15 December 2013 at 09:38:28 UTC, deadalnix wrote:Resulting in people giving name like TestT1, TestT2 as enum values in C++. As a result, you end up with the same verbosity as in D, without the possibility of using 'with'.I've usually seen the "namespace" or "struct "approach, eg: namespace CheckerBoardColor // or struct CheckerBoardColor { enum Enumeration { Red, Black, }; }; This allows using "CheckerBoardColor::Red", which (IMO) is nice and verbose. you can use "using CheckerBoardColor" for the equivalent of "with" (namespace only). Unfortunatly, the actual enum "type" is "CheckerBoardColor::Enumeration", which is strangely verbose.
Dec 15 2013
On Sunday, 15 December 2013 at 12:40:53 UTC, monarch_dodra wrote:On Sunday, 15 December 2013 at 09:38:28 UTC, deadalnix wrote:I'd rather do this: namespace CheckerBoardColorNamespace { enum CheckerBoardColor { Red, Black }; }; using CheckerBoardColorNamespace::CheckerBoardColor; auto v = CheckerBoardColor::Red; int main() { using namespace CheckerBoardColorNamespace; auto v = Red; } ...and you get to have a nice name for the enum type.Resulting in people giving name like TestT1, TestT2 as enum values in C++. As a result, you end up with the same verbosity as in D, without the possibility of using 'with'.I've usually seen the "namespace" or "struct "approach, eg: namespace CheckerBoardColor // or struct CheckerBoardColor { enum Enumeration { Red, Black, }; }; This allows using "CheckerBoardColor::Red", which (IMO) is nice and verbose. you can use "using CheckerBoardColor" for the equivalent of "with" (namespace only). Unfortunatly, the actual enum "type" is "CheckerBoardColor::Enumeration", which is strangely verbose.
Dec 15 2013
On Sunday, 15 December 2013 at 15:01:47 UTC, Tommi wrote:I'd rather do this: namespace CheckerBoardColorNamespace { enum CheckerBoardColor { Red, Black }; }; using CheckerBoardColorNamespace::CheckerBoardColor; auto v = CheckerBoardColor::Red; int main() { using namespace CheckerBoardColorNamespace; auto v = Red; } ...and you get to have a nice name for the enum type.That's a C++11 extension. "CheckerBoardColor::Red" is not a legal value. There are no scoped enums in C++98/03. That said, nice trick for "using namespace CheckerBoardColorNamespace;" It's a nice way to emulate "with". Too bad this means the enum (AFAIK) can't be strongly C++11-stlye typed. BTH though, if I had C++11 in my workplace, I'd just class it and move on.
Dec 15 2013
monarch_dodra:I've been in enough large scale C++ projects to enjoy D's verbose approach. Sure, C++ is convenient and works 99% of the time. But all you need is for some retard to create a Global enum containing things like the words "Yes, No, True, False, Red, Black, White", and then he's ruined it for *everyone* on the project.By the way, I am not criticizing "D verbose approach". I have criticized the weak typing: enum Foo { good, bad } void main() { int x = Foo.good; // Weak typing. } And some people have criticized the verbosity in special situations, like this: enum Foo { good, bad } void bar(Foo f) {} void main() { // bar(bad); // Not enough bar(Foo.bad); } Bye, bearophile
Dec 15 2013
On Sunday, 15 December 2013 at 11:27:51 UTC, bearophile wrote:By the way, I am not criticizing "D verbose approach". I have criticized the weak typing: enum Foo { good, bad } void main() { int x = Foo.good; // Weak typing. }Hum... Well, it's not actually weak typing. It's strong typing with implicit cast *to* the base type (int by default). For example: enum Foo { a, b, c, } void foo(Foo) {} void main() { foo(1); //Nope. I want a Foo. } Whether this is a good or bad thing I don't know. If D where "just" D, I'd say it's a bad thing (it should require an explicit cast). However, arguably, there might be enough C heritage in D to justify it. As long as we don't have "int to enum" implicit conversion, I think it's fine.And some people have criticized the verbosity in special situations, like this: enum Foo { good, bad } void bar(Foo f) {} void main() { // bar(bad); // Not enough bar(Foo.bad); }I am of those that think this is a good thing.Bye, bearophile
Dec 15 2013
On Sunday, 15 December 2013 at 11:27:51 UTC, bearophile wrote:And some people have criticized the verbosity in special situations, like this: enum Foo { good, bad } void bar(Foo f) {} void main() { // bar(bad); // Not enough bar(Foo.bad); }A related discussion: http://forum.dlang.org/thread/lssmuukdltmooehlnfpf forum.dlang.org
Dec 15 2013
On Sunday, 15 December 2013 at 11:27:51 UTC, bearophile wrote:By the way, I am not criticizing "D verbose approach". I have criticized the weak typing: enum Foo { good, bad } void main() { int x = Foo.good; // Weak typing. }This is not a weak typing. An example of weak typing is array literal []. There is nothing wrong with converting enum to base type, since enum is always subset of base type. Explicit cast in such case is useless. What is your point against current behavior?And some people have criticized the verbosity in special situations, like this: enum Foo { good, bad } void bar(Foo f) {} void main() { // bar(bad); // Not enough bar(Foo.bad); } Bye, bearophilebecause 'bad' is undefined identifier, but I see your point.
Dec 15 2013
Am 15.12.2013 02:16, schrieb Joseph Rice:While I must first Admit I'm new to D. However; I have been a C/C++ programmer for 15 years. I am excited about D. One of the features I love is being able to access my legacy code. But there are some cases were a complete re-write/re-factor to D makes sense. I've come to it very frustrating code that has been stable for years now needs to be changed because of a language quirk. The main selling point about D is C/C++ is almost the same syntax, I see potential in D to replace C/C++. I've noticed that enum behavior is dramatically different. This is my opinion, but I see this as a flaw in D. Again let me repeat, My opinion. While I understand D's approach to enum's. It is a hard pill to swallow for an experienced programmer. The D compiler should know the type of the enum from the symbol. You should not have to type the NAME.element when doing a comparison or assignment. Declaring an enum FOO { one, two, three} should be the same as declaring a new type. So that when you declare `FOO bar;` in code, assignment and comparison of `bar` should know what bar is comprised of because it is of type enum FOO. Therefore anything of type enum FOO can only comprise of the values 'one', 'two', or 'three'. I've prepared 3 examples, a C, C++, and Finally D. All essentially the same code. You will notice that the D version, has some vast differences. For example you can not define an enum and declare the variable all at once. This gets me to the annoying part. assigning and Comparing. jrice Wayland:~/prj/enum_example$ gcc -o enum_c enum.c jrice Wayland:~/prj/enum_example$ g++ -o enum_cpp enum.cpp jrice Wayland:~/prj/enum_example$ dmd enum.d jrice Wayland:~/prj/enum_example$ ./enum_c It's test1 jrice Wayland:~/prj/enum_example$ ./enum_cpp It's test1 jrice Wayland:~/prj/enum_example$ ./enum It's test1 jrice Wayland:~/prj/enum_example$ cat enum.c #include <stdio.h> void main() { enum TEST { test1=0, test2 } test; test = test1; switch (test) { case test1: printf("It's test1\n"); break; case test2: printf("It's test2\n"); break; default: break; } } jrice Wayland:~/prj/enum_example$ cat enum.cpp #include <iostream> using namespace std; int main() { enum TEST { test1=0, test2 } test; test = test1; switch (test) { case test1: cout << "It's test1" << endl; break; case test2: cout << "It's test2" << endl; break; default: break; } return 0; } jrice Wayland:~/prj/enum_example$ cat enum.d import std.stdio; void main() { enum TEST { test1=0, test2 }; TEST test = TEST.test1; switch (test) { case TEST.test1: writeln("It's test1"); break; case TEST.test2: writeln("It's test2"); break; default: break; } } So as you can see, D is just awkward, and it becomes tedious especially if you have many many many values in the enum. So D language Designers and maintainers: 1st I understand your reasons, it makes it un-ambiguous, becaause you know exactly which enum `test1` belongs too. 2nd What the heck, why do I have to type extra. It makes porting a little mre frustrating, and makes me question using D in the first place. 3rd I'm Pleading to you to consider making both syntax's valid. The Old C/C++ way, and the D way. If you have too, make compiler flag.It follows the same approach as many other modern languages, even C++ has them nowadays. Obviously, the world at large has come to the conclusion that having enum identifiers creeping into global scope in C was not a good idea. -- Paulo
Dec 15 2013
On 15 December 2013 01:16, Joseph Rice <ricejm01 gmail.com> wrote:So as you can see, D is just awkward, and it becomes tedious especially if you have many many many values in the enum.You are in for a shock when you hear about C++11 http://www.stroustrup.com/C++11FAQ.html#enum That particular FAQ gives a good overview of the rationale of D enums when someone comes from a C++ background, and we should have something similar to describe the difference in the Porting / Interfacing to C/C++ pages.
Dec 15 2013