www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - "toString(enum.value)" How?

reply Ingo Oeser <ioe-news rameria.de> writes:
Hi,

while trying to code/port some stuff heavily relying on enums,
I asked myself, whether there is a nice and elegant way
to actually get the name of an enum value as string.

enum Funny {
        UNKNOWN,
        MAKES_ME_SMILE,
        LAUGHING_OUT_LOUD,
        ROLLING_ON_THE_FLOOR_LAUGHING
}

void main()
{
        Funny joke = Funny.LAUGHING_OUT_LOUD;
        wrifeln("%s", toString(joke));
}

should print "Funny.LAUGHING_OUT_LOUD". I could also
live with "LAUGHING_OUT_LOUD". But keeping these two tables
(string[] and enum) in sync requires some kind of preprocessor 
and D has none.

How is that kind of problem solved in D WITHOUT 
keeping two tables?

Many thanks and Best Regards

Ingo Oeser
Jul 08 2007
next sibling parent Jason House <jason.james.house gmail.com> writes:
The topic of converting enums to strings has come up before.

IIRC, the problem is that enums tend to be used for one of two purposes: 
a collection of fixed constants, and bit fields/masks.  While the former 
may be easy to do, the latter presents a problem...  Especially when the 
values of different fields overlap.

Ingo Oeser wrote:
 Hi,
 
 while trying to code/port some stuff heavily relying on enums,
 I asked myself, whether there is a nice and elegant way
 to actually get the name of an enum value as string.
 
 enum Funny {
         UNKNOWN,
         MAKES_ME_SMILE,
         LAUGHING_OUT_LOUD,
         ROLLING_ON_THE_FLOOR_LAUGHING
 }
 
 void main()
 {
         Funny joke = Funny.LAUGHING_OUT_LOUD;
         wrifeln("%s", toString(joke));
 }
 
 should print "Funny.LAUGHING_OUT_LOUD". I could also
 live with "LAUGHING_OUT_LOUD". But keeping these two tables
 (string[] and enum) in sync requires some kind of preprocessor 
 and D has none.
 
 How is that kind of problem solved in D WITHOUT 
 keeping two tables?
 
 Many thanks and Best Regards
 
 Ingo Oeser
 

Jul 08 2007
prev sibling parent reply "Jarrett Billingsley" <kb3ctd2 yahoo.com> writes:
"Ingo Oeser" <ioe-news rameria.de> wrote in message 
news:f6r5mi$2q7n$1 digitalmars.com...
 How is that kind of problem solved in D WITHOUT
 keeping two tables?

Unfortunately the language also doesn't provide any way of querying information about an enum other than its min, max, and default values.. it would be nice, given a named enum, to get a .tupleof the valid values, where each item in the tuple would be an alias to one of the valid enum values. Furthermore, EnumValue.stringof would have to give a string representation of the actual enum value, rather than a string of the type as it does now (I think .stringof is still not 100% finished anyway..). With those two abilities, generating some kind of lookup table at compile-time would be very easy indeed. But of course as Jason pointed out, one issue is with flag enums. C# kind of solves this by allowing you to put a "Flags()" attribute or so on the enum, which gives the runtime a hint as to how to stringize a given enum value (it comes out as something like "Blah.A, Blah.B, Blah.C" if you have multiple values or'ed together). I'd even go so far as to say that the use of an enum as a simple list of constants and the use of an enum as a list of flags is divergent enough to warrant a new language construct -- i.e. "flags Blah { A, B, C }". You wouldn't have to manually specify the values as you have to with flag enums, and it makes sense to Or together multiple flag values; it usually doesn't make sense to Or together multiple values of a "constants" enum.
Jul 08 2007
next sibling parent reply Daniel919 <Daniel919 web.de> writes:
This would be nice:
Funny.tupleof should return a Tuple of values, like: "0 1 2 3"
Funny.names should return the names like: UNKNOWN, MAKES_ME_SMILE, ...

I guess with compile-time reflection we can also expect features like that.

Some time ago I was trying to do serialization, but getting the name of 
a member variable from a struct is not possible:
struct Foo { int x; int y; }; Foo foo;
writefln(foo.whatever[0]) should return "x";
Atm there is no builtin way to do this.


Daniel
Jul 09 2007
parent reply Ingo Oeser <ioe-news rameria.de> writes:
Daniel919 wrote:

 This would be nice:
 Funny.tupleof should return a Tuple of values, like: "0 1 2 3"
 Funny.names should return the names like: UNKNOWN, MAKES_ME_SMILE, ...

Doing it with tuples is only slightly useful, since there can be gaps in enums. That's why I would like to have the names of the enums members, only. Best Regards Ingo Oeser
Jul 10 2007
parent "Jarrett Billingsley" <kb3ctd2 yahoo.com> writes:
"Ingo Oeser" <ioe-news rameria.de> wrote in message 
news:f70i4s$2o0d$1 digitalmars.com...
 Doing it with tuples is only slightly useful, since there
 can be gaps in enums.

Not if the tuple was a tuple of aliases to the enum members. For example, something like this: enum X { A, B, C = 6 } alias X.A _A; alias X.B _B; alias X.C _C; template Tuple(T...) { alias T Tuple; } alias Tuple!(_A, _B, _C) XTupleof; .. foreach(val; XTupleof) writefln(val); this shows "0 1 6". This of course is just the manual implementation of what the compiler could do for us. Basically it'd become foreach(val; X.tupleof) writefln(val); and the tuple would be aliases to each value. Then you could do .stringof on val and get the name. And from there, it's a very short jump to generating the actual table. Or, as you said, if the compiler could just give us a .namesof or something like that, we wouldn't have to do anything at all ;)
Jul 10 2007
prev sibling parent Ingo Oeser <ioe-news rameria.de> writes:
Jarrett Billingsley wrote:
 Furthermore, EnumValue.stringof would have to give a string
 representation of the actual enum value, rather than a string of the type
 as it does now

That behavior would be perfect! This is also much better that min/max, since enums can contain holes. Enums are just a set of valid symbols with defined ordering within a scope.
 (I think .stringof is still not 100% finished anyway..).  With those two
 abilities, generating some kind of lookup table at compile-time would be
 very easy indeed.

And is very much needed. Just look how often that kind of stuff is implemented! Maybe we can have the best of both worlds and just get a string[enum foo] from any named enum, where we can iterate either through the keys or through the values.
 But of course as Jason pointed out, one issue is with flag enums.

They are nothing else but additional values for me. Consider: enum Foo { bar = 1, baz = 2, boo = 4, all = bar | baz | boo, } Foo.all is just an additional valid value. The way it is composed is nothing else but an implementation detail, which can change.
 I'd even go so far as to say that the
 use of an enum as a simple list of constants and the use of an enum as a
 list of flags is divergent enough to warrant a new language construct
 i.e. "flags

Yes, that is a completely new semantic, which is called "set" :-) Ok, that is actually a "set of enum values" which might be an interesting specialisation for the set template :-) We don't have that semantic now. But we have enums and they miss a useful method. That is my point. Maybe I should forward that thread to the "D" newsgroup? Best Regards Ingo Oeser
Jul 10 2007