Re: Getting enum from value

2017-08-06 Thread Kreikey via Digitalmars-d-learn

On Saturday, 5 August 2017 at 20:11:27 UTC, Matthew Remmel wrote:

On Saturday, 5 August 2017 at 18:26:10 UTC, Kreikey wrote:
On Saturday, 5 August 2017 at 15:33:57 UTC, Matthew Remmel 
wrote:
I feel like I'm missing something, but there has to be an 
easier way to convert a value into an enum than switching 
over every possible value: i.e


[...]


Capitals c = cast(Capitals)"Chicago";
writeln(c);// Illinois


I'm annoyed that I didn't think of trying to cast it. That 
works great if the value exists in the enum. It does something 
weird if the value doesn't though. This is my test.d file:


import std.stdio;

enum Foo {
A = "AV",
B = "BV"
}

void main() {
Foo k = cast(Foo)"BV"; // Works and prints correctly

k = cast(Foo)"CV";
writeln("Type: ", typeid(k));  // Type: test.Foo
writeln("Value: ", k);   // Value: cast(Foo)CV
}

The output shows the type being the Foo enum but the value is 
'cast(Foo)CV'. I would of expected an error or exception to be 
thrown if it wasn't able to cast into an actual enum member. Is 
this something with how the enums are implemented under the 
hood?


So I've come up with a concise way to do this. Given:

Capitals strToEnum(string myString) {
  Capitals instance = cast(Capitals)myString;
  if (![EnumMembers!Capitals].canFind(instance))
throw new Exception("can't convert that string to that enum");
  return instance;
}

do:

Capitals c = strToEnum("Chicagoo");

Not quite a one-liner, but pretty close. Turning it into a 
template is left to the user as an exercise ;)


Re: Getting enum from value

2017-08-05 Thread Kreikey via Digitalmars-d-learn

On Saturday, 5 August 2017 at 20:11:27 UTC, Matthew Remmel wrote:

On Saturday, 5 August 2017 at 18:26:10 UTC, Kreikey wrote:

On Saturday, 5 August 2017 at 15:33:57 UTC, Matthew Remmel


I'm annoyed that I didn't think of trying to cast it. That 
works great if the value exists in the enum. It does something 
weird if the value doesn't though. This is my test.d file:


import std.stdio;

enum Foo {
A = "AV",
B = "BV"
}

void main() {
Foo k = cast(Foo)"BV"; // Works and prints correctly

k = cast(Foo)"CV";
writeln("Type: ", typeid(k));  // Type: test.Foo
writeln("Value: ", k);   // Value: cast(Foo)CV
}

The output shows the type being the Foo enum but the value is 
'cast(Foo)CV'. I would of expected an error or exception to be 
thrown if it wasn't able to cast into an actual enum member. Is 
this something with how the enums are implemented under the 
hood?


That was my first post on this forum, so I'm glad it was at least 
a little bit useful :-D
I think the reasoning for no error on bad casts is that casting 
is a blunt instrument that assumes the programmer knows what he's 
doing, and it breaks the type system. So you'd want to use one of 
the aforementioned solutions if you're set on using enums in this 
way. You might also consider using associative arrays, but it's 
also a bit cumbersome. There's no way to get around searching:


  capitals = [
"Indiana" : "Indianapolis",
"Illinois" : "Chicago",
"Ohio" : "Columbus"
  ];
  auto r = capitals.byKeyValue.find!((a, b) => a.value == 
b)("Chicago");

  if (!r.empty) {
writeln(capitals[r.front.key]);
  } else {
writeln("not found");
  }

You could also define another associative array statesByCapital 
with the key : value orders reversed, and then you could also do 
statesByCapitol["Chicago"]. Of course then you'd have to keep 
things in sync if things change. But I discovered a neat trick 
you could use to generate such a two way mapping. You could 
define one array string[] capitals, and another array string[] 
states. Then you could do:


auto capitalsByState = assocArray(zip(states, capitals));
auto statesByCapital = assocArray(zip(capitals, states));

If your data doesn't change for the lifetime of the program, that 
looks like a nice way to do it.


Re: Getting enum from value

2017-08-05 Thread Kreikey via Digitalmars-d-learn

On Saturday, 5 August 2017 at 15:33:57 UTC, Matthew Remmel wrote:
I feel like I'm missing something, but there has to be an 
easier way to convert a value into an enum than switching over 
every possible value: i.e


[...]


Capitals c = cast(Capitals)"Chicago";
writeln(c);// Illinois