www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Design of reflective enums

reply renoX <renosky free.fr> writes:
Hello,
Kevin Bealer has started an implementation (two implementations in fact!) of
reflective enums, and I wanted to discuss the use case and the design of this
feature to make it as useful as possible.
Reflective enums have two useful properties that don't have normal enums:
- their label is printable
- it's possible to do a foreach on all the possible values.

In my opinion, for the reflective enums, the following constraint should apply:
- they should 'look like' normal enums as much as possible.
- then the printable label feature should be as simple to use as possible: this
feature will  probably be used much more often than the foreach feature.

For the API, the functions needed are:
a- Reflective Enum(REnum) list definition.
b. REnum variable definition.
c. Reference to an REnum label.
d. Print the label corresponding to the value of an REnum variable.
e. Iterate over all possible value in an REnum list.
f. Iterate over all possible labels in an REnum list (I've added this one by
symmetry).

(a) Takes a name and either define (1) an enum of this name plus some functions
to print enum labels and iterate over it, or alternatively as in the original
code it can return a 'thing' (struct for example as it in the initial
implementation) (2) which contain the enum and functions.
I'm not sure which is best.

(e) and (f) reminds me of associate arrays, maybe a function to generate an
associative array from the enum list would be enough..

I'm trying to create functions to (e) and (f), but I have trouble to make my
code work currently: debugging template code is not very easy..

renoX
Feb 19 2007
next sibling parent Michiel <nomail please.com> writes:
renoX wrote:

 Hello,
 Kevin Bealer has started an implementation (two implementations in fact!) of
reflective enums, and I wanted to discuss the use case and the design of this
feature to make it as useful as possible.
 Reflective enums have two useful properties that don't have normal enums:
 - their label is printable
 - it's possible to do a foreach on all the possible values.
What about this one: - it's possible to do a slice and get a new enum with a subset of the original enum values (and labels) You could do something like this: enum Weekday {MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY} foreach (day; Weekday[MONDAY..FRIDAY]) { ... } -- Michiel
Feb 19 2007
prev sibling next sibling parent reply Michiel <nomail please.com> writes:
renoX wrote:

 Hello,
 Kevin Bealer has started an implementation (two implementations in fact!) of
reflective enums, and I wanted to discuss the use case and the design of this
feature to make it as useful as possible.
 Reflective enums have two useful properties that don't have normal enums:
 - their label is printable
 - it's possible to do a foreach on all the possible values.
By the way, should this not be in the core language? -- Michiel
Feb 19 2007
parent reply renoX <renosky free.fr> writes:
Michiel Wrote:

 renoX wrote:
 
 Hello,
 Kevin Bealer has started an implementation (two implementations in fact!) of
reflective enums, and I wanted to discuss the use case and the design of this
feature to make it as useful as possible.
 Reflective enums have two useful properties that don't have normal enums:
 - their label is printable
 - it's possible to do a foreach on all the possible values.
By the way, should this not be in the core language?
Well I think that Ada does it in the core language (but I think that they are not printable), it is able to define enum as an index array as you suggest in your second email. As the more I look at D, the more I find it similar to Ada, it is perhaps a good idea to make them those enhanced enum in the core language, and as an improvement to Ada those enum should be printable (maybe as an option to save memory) . In the meantime, my trial is below, but it doesn't work when there are two enums: the two toString conflicts, even though they should not because their parameter is a different enum type. Should I report this as a bug? renoX import std.stdio; import std.metastrings; template Find(char[] A, char[] B) { static if (A.length < B.length) { const int Find = -1; } else static if (A[0..B.length] == B) { const int Find = 0; } else static if (-1 == Find!(A[1..$], B)) { const int Find = -1; } else { const int Find = 1 + Find!(A[1..$], B); } } template SplitFirst(char[] A, char[] B) { const int Location = Find!(A, B); static if (Location == -1) { const char[] First = A; const char[] Rest = ""; } else { const char[] First = A[0..Location]; const char[] Rest = A[Location+B.length..$]; } } template ChompSpaces(char[] A) { static if (A.length) { static if (A[0] == ' ') { alias ChompSpaces!(A[1..$]) ChompSpaces; } else static if (A[$-1] == ' ') { alias ChompSpaces!(A[0..$-1]) ChompSpaces; } else { alias A ChompSpaces; } } else { const char[] ChompSpaces = ""; } } template SplitChomp(char[] A, char[] B) { alias ChompSpaces!(SplitFirst!(A, B).First) First; alias ChompSpaces!(SplitFirst!(A, B).Rest) Rest; } template EnumName(char[] A) { alias SplitChomp!(SplitFirst!(A, ",").First, "=").First EnumName; } template EnumAssign(char[] A) { alias SplitChomp!(SplitFirst!(A, ",").First, "=").Rest EnumAssign; } template EnumValue(char[] A, int i) { static if (EnumAssign!(A) == "") { const int EnumValue = i; } else { const int EnumValue = mixin(ParseInteger!(EnumAssign!(A)).value); } } template EnumListName(char[] A) { alias SplitChomp!(A, "{").First EnumListName; } template EnumBody(char[] A) { alias SplitChomp!(SplitFirst!(A, "}").First, "{").Rest EnumBody; } template BuildOneEnum(char[] A, int i) { const char[] BuildOneEnum = "const int "~EnumName!(A)~" = "~ ToString!(EnumValue!(A, i))~";\n"; } template BuildEnums(char[] A, int i) { static if (SplitChomp!(A, ",").Rest.length == 0) { const char[] BuildEnums = BuildOneEnum!(A, EnumValue!(A, i)); } else { const char[] BuildEnums = BuildOneEnum!(SplitChomp!(A, ",").First, EnumValue!(A, i)) ~ BuildEnums!(SplitChomp!(A, ",").Rest, EnumValue!(A, i)+1); } } template BuildOneCase(char[] A, int i, bool full) { static if (!full) { const char[] BuildOneCase = "case "~ToString!(EnumValue!(A, i))~ ": return \""~EnumName!(A)~"\";\n"; } else { const char[] BuildOneCase = "case "~ToString!(EnumValue!(A, i))~ ": return \""~EnumName!(A)~"("~ToString!(EnumValue!(A, i))~")\";\n"; } } template BuildEnumCases(char[] A, int i, bool full) { static if (SplitChomp!(A, ",").Rest.length == 0) { const char[] BuildEnumCases = BuildOneCase!(A, EnumValue!(A, i), full); } else { const char[] BuildEnumCases = BuildOneCase!(SplitChomp!(A, ",").First, EnumValue!(A, i), full) ~ BuildEnumCases!(SplitChomp!(A, ",").Rest, EnumValue!(A, i)+1,full); } } template BuildEnumSwitch(char[] A, int i, bool full) { const char[] BuildEnumSwitch = "switch(x) {"~ BuildEnumCases!(A, i, full) ~ "default: "~ " throw new Exception(\"enumeration out of range\");" "}"; } template BuildEnumElem(char[] A, char[]enumListName, int i, int ekv) { static if (ekv == 0) { const char[] BuildEnumElem = enumListName~"."~EnumName!(A)~", "; } ; static if (ekv == 1) { const char[] BuildEnumElem = "\""~EnumName!(A)~"\", "; }; static if (ekv == 2) { const char[] BuildEnumElem = ToString!(EnumValue!(A, i))~", "; } } // build the list of key if key is true, the list of values if key is false template BuildEnumList(char[] A, char[]enumListName, int i, int ekv) { static if (SplitChomp!(A, ",").Rest.length == 0) { const char[] BuildEnumList = BuildEnumElem!(A, enumListName, EnumValue!(A, i), ekv); } else { const char[] BuildEnumList = BuildEnumElem!(SplitChomp!(A, ",").First, enumListName, EnumValue!(A, i), ekv)~ BuildEnumList!(SplitChomp!(A, ",").Rest, enumListName, EnumValue!(A, i)+1, ekv); } } //to be mature it should parse also the EnumBaseType template DefEnum(char[] enum_str) { mixin("enum "~enum_str~";"); mixin( "static char[] toString("~EnumListName!(enum_str)~" val) { int x = val; "~ BuildEnumSwitch!(EnumBody!(enum_str), 0, false)~ " }" ); mixin( "static char[] toFullString("~EnumListName!(enum_str)~" val) { int x = val; "~ BuildEnumSwitch!(EnumBody!(enum_str), 0, true)~ " }" ); mixin( "const "~EnumListName!(enum_str)~"[] "~EnumListName!(enum_str)~"_elem ="~ " [ "~ BuildEnumList!(EnumBody!(enum_str), EnumListName!(enum_str), 0, 0)~ " ];" ); mixin( "const char[][]"~EnumListName!(enum_str)~"_keys = [ "~ BuildEnumList!(EnumBody!(enum_str), EnumListName!(enum_str), 0, 1)~ " ];" ); mixin( "const int[]"~EnumListName!(enum_str)~"_values = [ "~ BuildEnumList!(EnumBody!(enum_str), EnumListName!(enum_str), 0, 2)~ " ];" ); } int main(char[][] args) { // mixin DefEnum!("LEnum2 {other=2, cont, end2=15, ps}"); mixin DefEnum!("LEnum {start, middle, end=10, ps, pps,}"); LEnum s = LEnum.start; writefln("s is %s, with name %s full name '%s'\n", s, toString(s), toFullString(s)); foreach(i,v; LEnum_elem) { writefln("Enum %d has name=%s value %d", i, toString(v), v); } // LEnum2 o = LEnum2.other; // writefln("o is %s, with name %s full name '%s'\n", o, toString(o), toFullString(o)); foreach(i,v; LEnum_keys) { writefln("Enum %d has name=%s and value %d", i, v, LEnum_values[i]); } foreach(i,v; LEnum_values) { writefln("Enum %d has name=%s value %d", i, toString(cast(LEnum)v), v); } return 0; }
Feb 19 2007
parent reply "Andrei Alexandrescu (See Website For Email)" <SeeWebsiteForEmail erdani.org> writes:
renoX wrote:
 Michiel Wrote:
 
 renoX wrote:

 Hello,
 Kevin Bealer has started an implementation (two implementations in fact!) of
reflective enums, and I wanted to discuss the use case and the design of this
feature to make it as useful as possible.
 Reflective enums have two useful properties that don't have normal enums:
 - their label is printable
 - it's possible to do a foreach on all the possible values.
By the way, should this not be in the core language?
Well I think that Ada does it in the core language (but I think that they are not printable), it is able to define enum as an index array as you suggest in your second email. As the more I look at D, the more I find it similar to Ada, it is perhaps a good idea to make them those enhanced enum in the core language, and as an improvement to Ada those enum should be printable (maybe as an option to save memory) .
On the contrary, I think it would be great if it were _not_ in the core language, and I'd be happy if a library enum was so good, it would cause deprecation of the built-in one. Andrei
Feb 19 2007
next sibling parent reply Michiel <nomail please.com> writes:
Andrei Alexandrescu (See Website For Email) wrote:

 Well I think that Ada does it in the core language (but I think that
 they are not printable), it is able to define enum as an index array
 as you suggest in your second email.
 As the more I look at D, the more I find it similar to Ada, it is
 perhaps a good idea to make them those enhanced enum in the core
 language, and as an improvement to Ada those enum should be printable
 (maybe as an option to save memory) .
On the contrary, I think it would be great if it were _not_ in the core language, and I'd be happy if a library enum was so good, it would cause deprecation of the built-in one.
That's a strange thing to hope for. There are advantages to having a feature in the core language instead of a library. Several of them are summed up on the website. In this case: * The syntax will be nice and clean. * The compiler knows exactly what you mean and can optimize accordingly. Those are not true of library implementations. -- Michiel
Feb 19 2007
parent "Andrei Alexandrescu (See Website For Email)" <SeeWebsiteForEmail erdani.org> writes:
Michiel wrote:
 Andrei Alexandrescu (See Website For Email) wrote:
 
 Well I think that Ada does it in the core language (but I think that
 they are not printable), it is able to define enum as an index array
 as you suggest in your second email.
 As the more I look at D, the more I find it similar to Ada, it is
 perhaps a good idea to make them those enhanced enum in the core
 language, and as an improvement to Ada those enum should be printable
 (maybe as an option to save memory) .
On the contrary, I think it would be great if it were _not_ in the core language, and I'd be happy if a library enum was so good, it would cause deprecation of the built-in one.
That's a strange thing to hope for. There are advantages to having a feature in the core language instead of a library. Several of them are summed up on the website. In this case: * The syntax will be nice and clean. * The compiler knows exactly what you mean and can optimize accordingly. Those are not true of library implementations.
These particular advantages don't come forward in the case of enums. Core language features also have a lot of disadvantages, such as increasing the size of the language's definition, making the feature inherently rigid and hard to evolve, and putting the onus on the language implementer. I see how strings can be meaningfully made part of the language, but instead of beefing up enums to the behemoth they are in Java, it's much more attractive to allowing libraries to do that. Andrei
Feb 19 2007
prev sibling parent reply Serg Kovrov <kovrov no.spam> writes:
Andrei Alexandrescu (See Website For Email) wrote:
 On the contrary, I think it would be great if it were _not_ in the core 
 language, and I'd be happy if a library enum was so good, it would cause 
 deprecation of the built-in one.
It's a great idea! But there are few issues that should be addressed: 1. Library implementation of enums should be able to produce a typedef, just like built-in enums. 2. Built-in enums do not produce symbols in object files. Neither should library implementation. -- serg.
Feb 23 2007
parent reply renoX <renosky free.fr> writes:
Serg Kovrov a écrit :
 Andrei Alexandrescu (See Website For Email) wrote:
 On the contrary, I think it would be great if it were _not_ in the 
 core language, and I'd be happy if a library enum was so good, it 
 would cause deprecation of the built-in one.
It's a great idea! But there are few issues that should be addressed: 1. Library implementation of enums should be able to produce a typedef, just like built-in enums.
This is doable, unfortunately function overload on typedef/enum seems broken, so..
 2. Built-in enums do not produce symbols in object files. Neither should 
 library implementation.
Well for reflective enums, you need to store the strings somewhere.. renoX
Feb 23 2007
parent reply Michiel <nomail please.com> writes:
renoX wrote:

 2. Built-in enums do not produce symbols in object files. Neither
 should library implementation.
Well for reflective enums, you need to store the strings somewhere..
Not if it's a core feature. Every request for a label could be replaced by a literal by the compiler. -- Michiel
Feb 23 2007
parent reply renoX <renosky free.fr> writes:
Michiel a écrit :
 renoX wrote:
 
 2. Built-in enums do not produce symbols in object files. Neither
 should library implementation.
Well for reflective enums, you need to store the strings somewhere..
Not if it's a core feature. Every request for a label could be replaced by a literal by the compiler.
I think that we do not understand, I'm talking about 'reflective enums' not regular enums (after all the thread is 'design of reflective enums). Reflective are enums where you can print also the *label* associated with the enum, so there must be a function somewhere which have these label strings to be able to print the label at runtime. So the label strings must be of course stored in the binary for reflective enums. renoX
Feb 23 2007
parent reply Michiel <nomail please.com> writes:
renoX wrote:

 2. Built-in enums do not produce symbols in object files. Neither
 should library implementation.
Well for reflective enums, you need to store the strings somewhere..
Not if it's a core feature. Every request for a label could be replaced by a literal by the compiler.
I think that we do not understand, I'm talking about 'reflective enums' not regular enums (after all the thread is 'design of reflective enums). Reflective are enums where you can print also the *label* associated with the enum, so there must be a function somewhere which have these label strings to be able to print the label at runtime. So the label strings must be of course stored in the binary for reflective enums.
Yes, but it wouldn't be a symbol. Like I said, a request for a label could be replaced by a string literal by the compiler IF reflective enums were a core language feature. -- Michiel
Feb 24 2007
parent Daniel Keep <daniel.keep.lists gmail.com> writes:
Michiel wrote:
 renoX wrote:
 
 2. Built-in enums do not produce symbols in object files. Neither
 should library implementation.
Well for reflective enums, you need to store the strings somewhere..
Not if it's a core feature. Every request for a label could be replaced by a literal by the compiler.
I think that we do not understand, I'm talking about 'reflective enums' not regular enums (after all the thread is 'design of reflective enums). Reflective are enums where you can print also the *label* associated with the enum, so there must be a function somewhere which have these label strings to be able to print the label at runtime. So the label strings must be of course stored in the binary for reflective enums.
Yes, but it wouldn't be a symbol. Like I said, a request for a label could be replaced by a string literal by the compiler IF reflective enums were a core language feature.
The key here is *at runtime*. enum CompressionLevel { None = 0, Minimal = 1, Normal = 2, Maximal = 3 } { CompressionLevel cl = some_function(); writefln( toFullString(cl) ); } In order for the toFullString function to work, the string must be stored somewhere in the executable so that it is accessible at runtime. At least, I think that's what renoX is talking about :3 -- Daniel -- Unlike Knuth, I have neither proven or tried the above; it may not even make sense. v2sw5+8Yhw5ln4+5pr6OFPma8u6+7Lw4Tm6+7l6+7D i28a2Xs3MSr2e4/6+7t4TNSMb6HTOp5en5g6RAHCP http://hackerkey.com/
Feb 24 2007
prev sibling next sibling parent reply "Andrei Alexandrescu (See Website For Email)" <SeeWebsiteForEmail erdani.org> writes:
renoX wrote:
 Hello,
 Kevin Bealer has started an implementation (two implementations in fact!) of
reflective enums, and I wanted to discuss the use case and the design of this
feature to make it as useful as possible.
 Reflective enums have two useful properties that don't have normal enums:
 - their label is printable
 - it's possible to do a foreach on all the possible values.
 
 In my opinion, for the reflective enums, the following constraint should apply:
 - they should 'look like' normal enums as much as possible.
Why? There is so much more freedom now, why limit ourselves. I think enums of arbitrary types should be allowed, including arrays, hashes, and user-defined types. An enumerated type is nothing but a closed set of named values. The names are always strings; the values can be of any (uniform) type. Andrei
Feb 19 2007
parent renoX <renosky free.fr> writes:
Andrei Alexandrescu (See Website For Email) a écrit :
 renoX wrote:
 Hello,
 Kevin Bealer has started an implementation (two implementations in 
 fact!) of reflective enums, and I wanted to discuss the use case and 
 the design of this feature to make it as useful as possible.
 Reflective enums have two useful properties that don't have normal enums:
 - their label is printable
 - it's possible to do a foreach on all the possible values.

 In my opinion, for the reflective enums, the following constraint 
 should apply:
 - they should 'look like' normal enums as much as possible.
Why?
Because that way a programmer used to normal enums can use reflective enums nearly identically.
 There is so much more freedom now, why limit ourselves. I think 
 enums of arbitrary types should be allowed, including arrays, hashes, 
 and user-defined types.
This would be a possible extension, but I wonder if it wouldn't be a bit redundant with associative array.. And I think that with the current implementation, it's would be very difficult,as we do our own parsing which is of course quite limited. Mmm, with this extension, my idea of reusing the built-in enum type doesn't work.. Kevin Bealer's implementation would work.. I'll try to tweak it to see if it's possible to make it feel more enum-like.
 An enumerated type is nothing but a closed set of named values. The 
 names are always strings; the values can be of any (uniform) type.
The names are not arbitrary strings but names/symbol: I wonder if a basic type 'symbol' would be interesting.. renoX
 
 
 Andrei
Feb 19 2007
prev sibling parent reply Kevin Bealer <kevinbealer gmail.com> writes:
renoX wrote:
 Hello,
 Kevin Bealer has started an implementation (two implementations in fact!) of
reflective enums, and I wanted to discuss the use case and the design of this
feature to make it as useful as possible.
 Reflective enums have two useful properties that don't have normal enums:
 - their label is printable
 - it's possible to do a foreach on all the possible values.
 
 In my opinion, for the reflective enums, the following constraint should apply:
 - they should 'look like' normal enums as much as possible.
 - then the printable label feature should be as simple to use as possible:
this feature will  probably be used much more often than the foreach feature.
 
 For the API, the functions needed are:
 a- Reflective Enum(REnum) list definition.
 b. REnum variable definition.
 c. Reference to an REnum label.
 d. Print the label corresponding to the value of an REnum variable.
 e. Iterate over all possible value in an REnum list.
 f. Iterate over all possible labels in an REnum list (I've added this one by
symmetry).
 
 (a) Takes a name and either define (1) an enum of this name plus some
functions to print enum labels and iterate over it, or alternatively as in the
original code it can return a 'thing' (struct for example as it in the initial
implementation) (2) which contain the enum and functions.
 I'm not sure which is best.
 
 (e) and (f) reminds me of associate arrays, maybe a function to generate an
associative array from the enum list would be enough..
 
 I'm trying to create functions to (e) and (f), but I have trouble to make my
code work currently: debugging template code is not very easy..
 
 renoX
 
Your comment about e and f matches something I've been thinking. The action of iterating over the enum and in fact looking up the string are essentially similar to an associative array. Imagine these two definitions in regular D: enum Xyz_t { x = 10, y = 100, z = 201 }; char[][Xyz_t] Xyz_t_lookup; lookup[x] = "x"; lookup[y] = "y"; lookup[z] = "z"; Xyz_t[] Xyz_t_keys = Xyz_t_lookup.keys; char[][] Xyz_t_labels = ["x", "y", "z"]; Now, I can do all the above operations with these definitions. We could build a reflective enum that converted to this definition. The main thing that I would change is that instead of a regular associative array, we can define a compile-time associative array. We can be more efficient in a CTAA than an AA because all values are known at compile time -- we convert all lookups to switches. It would look like this: // given types T1 and T2 // constructed like this: // CTAA!(int, char[], "10, \"x\", 100, \"y\", 201, \"z\""); struct CTAA(T1, T2, E... values) { const T1[] keys = [10,100,201]; const T2[] values = ["x","y","z"]; int opApply(int delegate(T1 k, T2 label) dg) { int rv; rv = dg(10, "x"); if (rv) return rv; rv = dg(100, "y"); if (rv) return rv; rv = dg(201, "z"); if (rv) return rv; return 0; } T1 getKey(T2 label) { switch(label) { case "x": return 10; case "y": return 100; case "z": return 201; default: throw new Exception("unknown label"); } } T2 getLabel(T1 key) { switch(label) { case 10: return "x"; case 100: return "y"; case 201: return "z"; default: throw new Exception("unknown enum"); } } } Note that the "\"x\"" stuff is a bit awkward but the reflective enum would be a wrapper around the AA; since it knows that it's 'strings' are just C identifiers, it can omit the escaped quotes in its initializer. Also, since the CTAA is not a real AA there is no reason not to provide the translation in both directions as shown above -- it's not really an AA just a quick way to define a couple of handy switch statements. In principle, switch/case should be more or less always be faster than actual AAs. Kevin
Feb 19 2007
parent reply renoX <renosky free.fr> writes:
Kevin Bealer Wrote:
 renoX wrote:
 Hello,
 Kevin Bealer has started an implementation (two implementations in fact!) of
reflective enums, and I wanted to discuss the use case and the design of this
feature to make it as useful as possible.
 Reflective enums have two useful properties that don't have normal enums:
 - their label is printable
 - it's possible to do a foreach on all the possible values.
 
 In my opinion, for the reflective enums, the following constraint should apply:
 - they should 'look like' normal enums as much as possible.
 - then the printable label feature should be as simple to use as possible:
this feature will  probably be used much more often than the foreach feature.
 
 For the API, the functions needed are:
 a- Reflective Enum(REnum) list definition.
 b. REnum variable definition.
 c. Reference to an REnum label.
 d. Print the label corresponding to the value of an REnum variable.
 e. Iterate over all possible value in an REnum list.
 f. Iterate over all possible labels in an REnum list (I've added this one by
symmetry).
 
 (a) Takes a name and either define (1) an enum of this name plus some
functions to print enum labels and iterate over it, or alternatively as in the
original code it can return a 'thing' (struct for example as it in the initial
implementation) (2) which contain the enum and functions.
 I'm not sure which is best.
 
 (e) and (f) reminds me of associate arrays, maybe a function to generate an
associative array from the enum list would be enough..
 
 I'm trying to create functions to (e) and (f), but I have trouble to make my
code work currently: debugging template code is not very easy..
 
 renoX
 
Your comment about e and f matches something I've been thinking. The action of iterating over the enum and in fact looking up the string are essentially similar to an associative array. Imagine these two definitions in regular D: enum Xyz_t { x = 10, y = 100, z = 201 }; char[][Xyz_t] Xyz_t_lookup; lookup[x] = "x"; lookup[y] = "y"; lookup[z] = "z"; Xyz_t[] Xyz_t_keys = Xyz_t_lookup.keys; char[][] Xyz_t_labels = ["x", "y", "z"]; Now, I can do all the above operations with these definitions.
Agreed, in fact we don't need toString functions, the arrays are enough. [cut]
 In principle, switch/case should be more or less always be faster than 
 actual AAs.
I must admit that I don't know at all what will be faster at runtime, but in some case the switch/case can be done at compile-time, which is a win. Also if efficiency is a concern, I wonder if it would be useful if in the case when there is no '=' in the enum definition (a not so rare case), we could use a regular array for the lookup (lookup == labels) , the only problem then is that we'd loose type safety for the lookups.. renoX
Feb 20 2007
parent reply renoX <renosky free.fr> writes:
I've ran into trouble trying to implement the associative array: 
apparently it's not possible to build an associative array at compile time.

Added to that the fact that overloading of functions doesn't work 
correctly on enums, the implementation of good reflective enum starts to 
look really difficult..

So it's a choice between
-using your initial implementation, which is not typesafe..
-restricting reflective enums to enums without '=' ie with values going 
0,1,2..
-waiting that Walter fix the current limitations on associative arrays 
or the bug(?) on function overloading with enums (overloading with a 
typedef has the same issue, so maybe it's me who doesn't understand the 
overload behaviour?)..


:-(
renoX
Feb 20 2007
parent Kevin Bealer <kevinbealer gmail.com> writes:
renoX wrote:
 I've ran into trouble trying to implement the associative array: 
 apparently it's not possible to build an associative array at compile time.
 
 Added to that the fact that overloading of functions doesn't work 
 correctly on enums, the implementation of good reflective enum starts to 
 look really difficult..
 
 So it's a choice between
 -using your initial implementation, which is not typesafe..
 -restricting reflective enums to enums without '=' ie with values going 
 0,1,2..
 -waiting that Walter fix the current limitations on associative arrays 
 or the bug(?) on function overloading with enums (overloading with a 
 typedef has the same issue, so maybe it's me who doesn't understand the 
 overload behaviour?)..
 
 
 :-(
 renoX
I want to make clear -- efficiency is important to me, at least if this is to be a replacement for enum, efficiency should be as much as is attainable, which should be a lot if it happens at compile time. Just to clarify my previous idea, when I say 'CTAA', I don't mean building a real AA at compile time. I mean building something that works like an AA as far as lookups, but the contents are readonly and added to the container at compile time. My idea is to get maximal efficiency of the type that most likely can't be had with a real AA. The ultimate efficiency in this case would be to have *lookup* happen at compile time for users of the class, though this can only happen in those cases where the search term is constant at compile time. In other cases, something like a switch would be my preference. Of course for the case of a reflective enum, looking up the label is probably not too common so it could be done some other way, but I'm thinking the CTAA should be as fast as possible. What I'm imagining is something like this: CTAA!("dog, bear, cat, snake, whiskey, soda") foo; const char[] x = foo.find!("dog")(); // A const char[] x = "bear"; // B My hope is for a design where statement A is transformed into statement B at compile time. Kevin
Feb 20 2007