www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Can someone explain this?

reply Jeff <massung gmail.com> writes:
I'm trying to get the values of an enum at compile-time and 
running into a behavior I don't understand.

Consider the following enum:

enum A {x="foo", y="bar"}

And now, I just want to print out the values of A at runtime 
(e.g. A.x = "foo").

void main()
{
     static foreach(i, op; EnumMembers!A)
     {
         writeln("A." ~ op.to!string ~ " = " ~ op);
     }
}

Okay, the above works. But, I'm not sure why?

If I just do writeln(op), it prints out x and y, which is the 
same if I do op.to!string. If I use a mixin... mixin("\"" ~ op ~ 
"\"") then it prints foo and bar.

So, I'm guessing there's something going on under-the-hood using 
the ~ operator with the enum and I'd like to understand what it 
is.

Likewise, if there's an easier method of getting the "value of 
enum" I haven't discovered yet, that'd be just as nice to know. ;)

Thanks!
Feb 06
next sibling parent Jeff <massung gmail.com> writes:
Also wanted to note that if I do:

string enumValue = op;
writeln(enumValue);

Then it also outputs foo and bar. So, why would the behavior of 
op.to!string not be the same?
Feb 06
prev sibling next sibling parent MoonlightSentinel <moonlightsentinel disroot.org> writes:
On Saturday, 6 February 2021 at 14:39:38 UTC, Jeff wrote:
 So, I'm guessing there's something going on under-the-hood 
 using the ~ operator with the enum and I'd like to understand 
 what it is.
Enum to string conversion is usually implemented using the name of the enum member, regardless of it's value (which might be any type). String concatenation is not defined for A, so the enum member is implicitly converted to it's base type (see [1], paragraph 5).
 Likewise, if there's an easier method of getting the "value of 
 enum" I haven't discovered yet, that'd be just as nice to know. 
 ;)
You can use an is expression to determine the base type... ``` is(A BaseType == enum) ``` ...and use `cast(BaseType) A.foo` [1] https://dlang.org/spec/enum.html#named_enums
Feb 06
prev sibling parent reply Adam D. Ruppe <destructionator gmail.com> writes:
On Saturday, 6 February 2021 at 14:39:38 UTC, Jeff wrote:
 Okay, the above works. But, I'm not sure why?
Phobos's enum conversion always looks at the identifier, whereas the rest of the language looks at the value. Remember phobos' writeln forwards to the rest of its conversions just like `to`. So in the language like string s = op; // gives the value under language rules auto s = cast(string) op; // the value under language rules to!string(op) // goes through the library's conversion functions and thus gives the name The idea is the library tries to be more consistent and names are generally nice: enum ERROR { OK = 1, FILE_NOT_FOUND = 2, ETC = 3 } writeln(error); // FILE_NOT_FOUND prolly better than 2 here string s = "OK"; ERROR e = to!ERROR(s); // looks it up by name So it is generally nice and then it does it consistently for string values too.
 So, I'm guessing there's something going on under-the-hood 
 using the ~ operator with the enum and I'd like to understand 
 what it is.
mixin and ~ follow language rules and thus work on the value.
 Likewise, if there's an easier method of getting the "value of 
 enum" I haven't discovered yet, that'd be just as nice to know.
So when you're writelning, do something under language rules first so Phobos doesn't see the static type. If phobos doesn't know it is is an enum, it is forced to work with a value too. Easiest is to just cast it: writeln(cast(string) op);
Feb 06
parent Jeff <massung gmail.com> writes:
On Saturday, 6 February 2021 at 15:00:45 UTC, Adam D. Ruppe wrote:
 On Saturday, 6 February 2021 at 14:39:38 UTC, Jeff wrote:
 Okay, the above works. But, I'm not sure why?
Phobos's enum conversion always looks at the identifier, whereas the rest of the language looks at the value.
...
 to!string(op) // goes through the library's conversion
This makes sense and is what I was missing. Thanks!
Feb 06