www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - what about typed enums?

reply dennis luehring <dl.soluz gmx.net> writes:
could be a nice feature for string / object (and other) mappings

normaly:
[int] enum color { red, green, blue }

what about other types? like

char[] enum color { red="the color red", green="the color green", 
blue="the color blue" }

for direkt mapping of string or other values? better than

enum color{ red, green, blue }
char[] color_str[color.size]=["the color red", "the color green", "the 
color blue"]

usefull?
Nov 13 2005
next sibling parent dennis luehring <dl.soluz gmx.net> writes:
dennis luehring wrote:
 could be a nice feature for string / object (and other) mappings
 
 normaly:
 [int] enum color { red, green, blue }
 
 what about other types? like
 
 char[] enum color { red="the color red", green="the color green", 
 blue="the color blue" }
 
 for direkt mapping of string or other values? better than
 
 enum color{ red, green, blue }
 char[] color_str[color.size]=["the color red", "the color green", "the 
 color blue"]
 
 usefull?
 
 

"only as an more-handy feature" something like an per-const-symbol-referenceable map (with fix int based key and variable value) in c++: map<int, string> color maybe in d: char[] enum color { red, green, blue } i can code this with consts and strings in c++/d like this const char[] red = "the red color"; const char[] green = "the green color"; const char[] blue = "the blue color"; but i lost the color scope
Nov 13 2005
prev sibling next sibling parent reply Mike Parker <aldacron71 yahoo.com> writes:
dennis luehring wrote:
 could be a nice feature for string / object (and other) mappings
 
 normaly:
 [int] enum color { red, green, blue }
 
 what about other types? like

You can use any of the built-in types you want (but not arrays of built-in types) enum : ushort color { } enum : char color { } and so on
 
 char[] enum color { red="the color red", green="the color green", 
 blue="the color blue" }
 
 for direkt mapping of string or other values? better than
 
 enum color{ red, green, blue }
 char[] color_str[color.size]=["the color red", "the color green", "the 
 color blue"]
 
 usefull?

I don't see strings as enums being useful. What would be the default values? How would you implement auto incrementation of default values? If you really want strings, and not enumerated values, then an array of strings will get you what you want in this case. What *would* be useful would be a way to convert enum values to strings automatically, i.e. color.red converts to "red" or "color.red", through a function call.
Nov 13 2005
parent reply renox <renosky free.fr> writes:
Mike Parker wrote:
 dennis luehring wrote:

 I don't see strings as enums being useful. What would be the default 
 values? How would you implement auto incrementation of default values? 
 If you really want strings, and not enumerated values, then an array of 
 strings will get you what you want in this case.
 
 What *would* be useful would be a way to convert enum values to strings 
 automatically, i.e. color.red converts to "red" or "color.red", through 
 a function call.

I agree completely: it's always annoying to display number for enums to the user, or to do the conversion by hand. The only annoying part of enum to string is that as you've said, there are at least two different conversion: red or color.red, and maybe module_name.color.red would be useful also. It's isn't a major issue, one should be picked at the default (my vote goes to color.red) and the other ones accessible with an additionnal parameter: to_string(short), to_string(full) for example. On one hand it adds 'syntaxic sugar' only for enum (I don't see how this could be reused elsewhere), on the other hand enums are important. Regards
Nov 14 2005
parent reply BCS <BCS_member pathlink.com> writes:
This is just a hack for the syntax but how about something like this:

|enum X
|{
|  A = 1 : "The letter A\n" ,
|  B : "The next Letter",
|  C : "Bla Bla Bla"
|};

where something like

| wrietf(X.A.toString)

prints out "The letter A\n" 
and 

| X a = X.B
| wrietf(a.toString)

prints out "The next Letter". 
This could be implemented with a hidden static array of some type.

e.g.

| X a = X.B
| wrietf(a.toString)

becomes

| X a = X.B
| wrietf(X.hiddenArray[a])




In article <dlbv5c$beo$1 digitaldaemon.com>, renox says...
Mike Parker wrote:
 dennis luehring wrote:

 I don't see strings as enums being useful. What would be the default 
 values? How would you implement auto incrementation of default values? 
 If you really want strings, and not enumerated values, then an array of 
 strings will get you what you want in this case.
 
 What *would* be useful would be a way to convert enum values to strings 
 automatically, i.e. color.red converts to "red" or "color.red", through 
 a function call.

I agree completely: it's always annoying to display number for enums to the user, or to do the conversion by hand. The only annoying part of enum to string is that as you've said, there are at least two different conversion: red or color.red, and maybe module_name.color.red would be useful also. It's isn't a major issue, one should be picked at the default (my vote goes to color.red) and the other ones accessible with an additionnal parameter: to_string(short), to_string(full) for example. On one hand it adds 'syntaxic sugar' only for enum (I don't see how this could be reused elsewhere), on the other hand enums are important. Regards

Nov 15 2005
next sibling parent dennis luehring <dl.soluz gmx.net> writes:
BCS wrote:
 This is just a hack for the syntax but how about something like this:
 
 |enum X
 |{
 |  A = 1 : "The letter A\n" ,
 |  B : "The next Letter",
 |  C : "Bla Bla Bla"
 |};

nice idea - but the value type should be defineable your example "char[] enum X" int[3] enum X { A = 1 : [1,2,3], B : [67,23,21], C : [21,22,33] }
 where something like
 
 | wrietf(X.A.toString)

writef(X.A.value) would be better (what if the type is int[3] :-)) ciao dennis
Nov 15 2005
prev sibling parent reply renox <renosky free.fr> writes:
BCS wrote:

 This is just a hack for the syntax but how about something like this:
 
 |enum X
 |{
 |  A = 1 : "The letter A\n" ,
 |  B : "The next Letter",
 |  C : "Bla Bla Bla"
 |};

I think that both Mike Parker and I thought more about something like this: enumstr X { A, B, C }; X x = A; Where x.toString returns "X.A", x.toString(short_name) returns "A", x.toString(full_name) returns "module_name.X.A". Your solution and that of dl.soluz gmx.net are more flexible but also necessitate more typing in the common case (just writing a *readable* trace file) i.e: enum X { THE_LABEL: "X.THE_LABEL" } and these generic solution do not allow the short_name, full_name 'hack', I think.. Regards, RenoX
 
 where something like
 
 | wrietf(X.A.toString)
 
 prints out "The letter A\n" 
 and 
 
 | X a = X.B
 | wrietf(a.toString)
 
 prints out "The next Letter". 
 This could be implemented with a hidden static array of some type.
 
 e.g.
 
 | X a = X.B
 | wrietf(a.toString)
 
 becomes
 
 | X a = X.B
 | wrietf(X.hiddenArray[a])
 
 
 
 
 In article <dlbv5c$beo$1 digitaldaemon.com>, renox says...
 
Mike Parker wrote:

dennis luehring wrote:

[]
I don't see strings as enums being useful. What would be the default 
values? How would you implement auto incrementation of default values? 
If you really want strings, and not enumerated values, then an array of 
strings will get you what you want in this case.

What *would* be useful would be a way to convert enum values to strings 
automatically, i.e. color.red converts to "red" or "color.red", through 
a function call.

I agree completely: it's always annoying to display number for enums to the user, or to do the conversion by hand. The only annoying part of enum to string is that as you've said, there are at least two different conversion: red or color.red, and maybe module_name.color.red would be useful also. It's isn't a major issue, one should be picked at the default (my vote goes to color.red) and the other ones accessible with an additionnal parameter: to_string(short), to_string(full) for example. On one hand it adds 'syntaxic sugar' only for enum (I don't see how this could be reused elsewhere), on the other hand enums are important. Regards


Nov 15 2005
parent dennis luehring <dl.soluz gmx.net> writes:
 I think that both Mike Parker and I thought more about something like this:
 
 enumstr X { A, B, C };
 X x = A;
 
 Where x.toString returns "X.A", x.toString(short_name) returns "A", 
 x.toString(full_name) returns "module_name.X.A".

but this is for the "we need a reflection system in d" section (for example i would like to have (class,method,variable,enum,...).name or something like this (only) avaiable at compiletime
 Your solution and that of dl.soluz gmx.net are more flexible but also 
 necessitate more typing in the common case (just writing a *readable* 
 trace file) i.e: enum X { THE_LABEL: "X.THE_LABEL" } and these generic 
 solution do not allow the short_name, full_name 'hack', I think..

i just want an enum-likeish stlye of data mapping (scope of const-symbols referencing to something with key/value ...) - the reflection or "code information" stuff is another section... ciao dennis
Nov 16 2005
prev sibling parent reply "Regan Heath" <regan netwin.co.nz> writes:
On Sun, 13 Nov 2005 17:33:30 +0100, dennis luehring <dl.soluz gmx.net>  
wrote:
 could be a nice feature for string / object (and other) mappings

 normaly:
 [int] enum color { red, green, blue }

 what about other types? like

 char[] enum color { red="the color red", green="the color green",  
 blue="the color blue" }

 for direkt mapping of string or other values? better than

 enum color{ red, green, blue }
 char[] color_str[color.size]=["the color red", "the color green", "the  
 color blue"]

 usefull?

Maybe, but also trivial to add yourself if you want. import std.stdio; enum COLOR { RED, GREEN, BLUE } const char[][COLOR] map; static this() { map[COLOR.RED] = "the color red"; map[COLOR.GREEN] = "the color green"; map[COLOR.BLUE] = "the color blue"; } //assert required because COLOR char[] toString(COLOR c) { assert(c <= COLOR.BLUE); return map[c]; } void main() { COLOR c = COLOR.RED; writefln(toString(c)); } Regan
Nov 15 2005
parent reply dennis luehring <dl.soluz gmx.net> writes:
 Maybe, but also trivial to add yourself if you want.

this is the perfect example of how i would (must) do it
 import std.stdio;
 
 enum COLOR { RED, GREEN, BLUE }
 const char[][COLOR] map;
 
 static this()
 {
   map[COLOR.RED] = "the color red";
   map[COLOR.GREEN] = "the color green";
   map[COLOR.BLUE] = "the color blue";
 }
 
 //assert required because COLOR
 char[] toString(COLOR c) { assert(c <= COLOR.BLUE); return map[c]; }
 
 void main()
 {
   COLOR c = COLOR.RED;
   writefln(toString(c));
 }
 
 Regan

why not in fewer lines of code (= fewer lines of errors) an why should i seperate my key (your enum) and my data (your map) over (in your very tiny tiny small example) 7 lines of code what if use an huge amount of different enums (with different types referecing to) - how big(more buggy) is my code then? // i use the syntax from BCS (post above) const char[] enum COLOR { RED : "the color red", GREEN : "the color green", BLUE : "the color blue" } void main() { COLOR c = COLOR.RED; // means c.key = COLOR.RED writefln(c.value); } or as an array of ints const int[3] enum COLOR { RED : [12,0,331], GREEN : [10,11,0], BLUE : [3,2,41] } void main() { COLOR c = COLOR.RED; // means c.key = COLOR.RED int[] values = c.value; } ok i know the syntax isn't very clear defined...
Nov 16 2005
next sibling parent reply "Regan Heath" <regan netwin.co.nz> writes:
On Wed, 16 Nov 2005 09:44:53 +0100, dennis luehring <dl.soluz gmx.net>  
wrote:
 Maybe, but also trivial to add yourself if you want.

this is the perfect example of how i would (must) do it
 import std.stdio;
  enum COLOR { RED, GREEN, BLUE }
 const char[][COLOR] map;
  static this()
 {
   map[COLOR.RED] = "the color red";
   map[COLOR.GREEN] = "the color green";
   map[COLOR.BLUE] = "the color blue";
 }
  //assert required because COLOR
 char[] toString(COLOR c) { assert(c <= COLOR.BLUE); return map[c]; }
  void main()
 {
   COLOR c = COLOR.RED;
   writefln(toString(c));
 }
  Regan

why not in fewer lines of code (= fewer lines of errors) an why should i seperate my key (your enum) and my data (your map) over (in your very tiny tiny small example) 7 lines of code what if use an huge amount of different enums (with different types referecing to) - how big(more buggy) is my code then?

I agree that seperating the key/value data can increase the chance of bugs, that is why I put them both in the same place in my code, it's a defensive programming habit which we should all have. I agree, you can improve this even further if the compiler verifies you have entered all your keys and values, perhaps with one of the syntaxes you mention. In the end however, it can already be done, the downside is almost insignificant and there are bigger fish to fry! Perhaps later on when Walter runs out of things to fix he'll look at adding a nice sugary syntax for this sort of thing. Regan
Nov 16 2005
next sibling parent Tomás Rossi <Tomás_member pathlink.com> writes:
In article <ops0bzpwgc23k2f5 nrage.netwin.co.nz>, Regan Heath says...
On Wed, 16 Nov 2005 09:44:53 +0100, dennis luehring <dl.soluz gmx.net>  
wrote:
 Maybe, but also trivial to add yourself if you want.

this is the perfect example of how i would (must) do it
 import std.stdio;
  enum COLOR { RED, GREEN, BLUE }
 const char[][COLOR] map;
  static this()
 {
   map[COLOR.RED] = "the color red";
   map[COLOR.GREEN] = "the color green";
   map[COLOR.BLUE] = "the color blue";
 }
  //assert required because COLOR
 char[] toString(COLOR c) { assert(c <= COLOR.BLUE); return map[c]; }
  void main()
 {
   COLOR c = COLOR.RED;
   writefln(toString(c));
 }
  Regan

why not in fewer lines of code (= fewer lines of errors) an why should i seperate my key (your enum) and my data (your map) over (in your very tiny tiny small example) 7 lines of code what if use an huge amount of different enums (with different types referecing to) - how big(more buggy) is my code then?

I agree that seperating the key/value data can increase the chance of bugs, that is why I put them both in the same place in my code, it's a defensive programming habit which we should all have. I agree, you can improve this even further if the compiler verifies you have entered all your keys and values, perhaps with one of the syntaxes you mention. In the end however, it can already be done, the downside is almost insignificant and there are bigger fish to fry! Perhaps later on when Walter runs out of things to fix he'll look at adding a nice sugary syntax for this sort of thing.

Hope he does, I've been longing for this feature in high level languages for a long time. It would be nice (and I suppose no performance waste would occur also). Tom
Nov 16 2005
prev sibling parent dennis luehring <dl.soluz gmx.net> writes:
 I agree that seperating the key/value data can increase the chance of  
 bugs,  that is why I put them both in the same place in my code,

but this will not help if the code rots over years (under the change of many stressed and poor expirienced programmers)
 it's a defensive programming habit which we should all have. 

under the right conditions :-) (see above statement)
 I agree, you can
 improve this even further if the compiler verifies you have entered all  
 your keys and values, perhaps with one of the syntaxes you mention.

thanks for beeing the first who understand what i want(mean)
 In the end however, it can already be done, the downside is almost  
 insignificant and there are bigger fish to fry! 
 Perhaps later on when
 Walter runs out of things to fix he'll look at adding a nice sugary 
 syntax  for this sort of thing.

hope will never die ciao dennis
Nov 16 2005
prev sibling parent reply Georg Wrede <georg.wrede nospam.org> writes:
dennis luehring wrote:
 Maybe, but also trivial to add yourself if you want.

this is the perfect example of how i would (must) do it
 import std.stdio;

 enum COLOR { RED, GREEN, BLUE }
 const char[][COLOR] map;

 static this()
 {
   map[COLOR.RED] = "the color red";
   map[COLOR.GREEN] = "the color green";
   map[COLOR.BLUE] = "the color blue";
 }

 //assert required because COLOR
 char[] toString(COLOR c) { assert(c <= COLOR.BLUE); return map[c]; }

 void main()
 {
   COLOR c = COLOR.RED;
   writefln(toString(c));
 }

 Regan

why not in fewer lines of code (= fewer lines of errors) an why should i seperate my key (your enum) and my data (your map) over (in your very tiny tiny small example) 7 lines of code what if use an huge amount of different enums (with different types referecing to) - how big(more buggy) is my code then? // i use the syntax from BCS (post above) const char[] enum COLOR { RED : "the color red", GREEN : "the color green", BLUE : "the color blue" } void main() { COLOR c = COLOR.RED; // means c.key = COLOR.RED writefln(c.value); } ok i know the syntax isn't very clear defined...

I've taught CS classes on graduate level for yeras. This is a very common thing to ask for. Then again, when doing professional programming, few people ask for this. --- It seems that enum usage examples in coursebooks often use things like: enum FOO {JAN, FEB, MAR} FOO now; // here some code to do something instructive :-) ... // later: switch (now) { JAN : writefln("January"); break; FEB : writefln("February"); break; } All of this creates an atmosphere where people think enums are somehow meant to be associated with strings that describe their name. Some of my students have later commented that what remains from having done the schoolbook enum excercises, is a feeling that "they are a contrived way of choosing between alternative outputs". Probably because that is what one sees when one runs such programs, and also because most of the effort (at that skill level) goes to getting the program to compile -- thus diverting attention from the few lines where enums got used for something. I guess a more productive way of teaching enums would be to create exercises in the previous chapter (which teaches some other subject) so that students' code ends up looking like: ... const int FRIEND = 1; const int RELATIVE = 2; const int OTHER = 3; ... And then in the next chapter introduce a shorter way of writing this, with the cool side effect of added type safety: enum PersonStatus {FRIEND, RELATIVE, OTHER} ... PersonStatus mobster; ... if (mobster == OTHER) {run for your life} Another common use of enums is to store properties in a size efficient and (for the computer) easy to use way: enum Need { NOTHING = 0, // ain't that the day! FOOD = 1, // nourishment needed SHELTER = 2, // a place to sleep in MEDIC = 4, // health needs attention MATE = 8, // the person is lonely } ... struct Person { Need needs = NOTHING; void newNeed(Need grief) {needs |= grief;} bool isLacking(Need what) {return needs & what;} bool isPathetic() {return needs == FOOD|SHELTER|MEDIC|MATE;} } As to the OP, a more constructive way of using enum COLOR would be something like: enum Color { RED = 0xff0000, GREEN = 0x00ff00, DARKGREY = 0x404040, }
Nov 16 2005
parent dennis luehring <dl.soluz gmx.net> writes:
nice answer but don't get me wrong im not talking about enum_string or 
something (because im not one of these unprof. devlopers. - im an very 
very defensiv programmer)

i talk about the syntactic sugar of merging some enum features with maps 
(just to reduce the amount of code (and errors)) while writing mapping stuff

the internal key should be stay int, but the second value should be 
defineable

example for an answer which goes in the right direction:
news://news.digitalmars.com:119/ops0bzpwgc23k2f5 nrage.netwin.co.nz

ciao dennis
Nov 16 2005