Thread overview
"toString(enum.value)" How?
Jul 08, 2007
Ingo Oeser
Jul 08, 2007
Jason House
Jul 09, 2007
Daniel919
Jul 10, 2007
Ingo Oeser
Jul 10, 2007
Ingo Oeser
July 08, 2007
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

July 08, 2007
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
> 
July 09, 2007
"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.


July 09, 2007
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
July 10, 2007
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
July 10, 2007
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
July 10, 2007
"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 ;)