Thread overview | |||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
December 07, 2013 iterate over enum name:value pairs | ||||
---|---|---|---|---|
| ||||
In Ali Çehreli very nice book there is this example of iterating over enum range which, as he notes, fails http://ddili.org/ders/d.en/enum.html enum Suit { spades, hearts, diamonds, clubs } foreach (suit; Suit.min .. Suit.max) { writefln("%s: %d", suit, suit); } spades: 0 hearts: 1 diamonds: 2 ← clubs is missing It seems like there is interest in iterating over the name:value pairs of an enum. Is this is already available with some D programming trick? |
December 07, 2013 Re: iterate over enum name:value pairs | ||||
---|---|---|---|---|
| ||||
Posted in reply to Jay Norwood | Jay Norwood:
> In Ali Çehreli very nice book there is this example of iterating over enum range which, as he notes, fails
>
> http://ddili.org/ders/d.en/enum.html
>
> enum Suit { spades, hearts, diamonds, clubs }
>
> foreach (suit; Suit.min .. Suit.max) {
> writefln("%s: %d", suit, suit);
> }
>
> spades: 0
> hearts: 1
> diamonds: 2
> ← clubs is missing
>
>
> It seems like there is interest in iterating over the name:value pairs of an enum. Is this is already available with some D programming trick?
min and max of enumeratinos are traps, I don't use them.
enum Suit { spades = -10, hearts = 10 }
Here max and min are worse than useless to list the enumeration members.
Also don't define "max" and "min" as members of the enumeration, because this causes a silent silly name clash:
enum Suit { spades, hearts, max, min, diamonds, clubs }
This is how you usually iterate them:
void main() {
import std.stdio, std.traits;
enum Suit { spades, hearts, diamonds, clubs }
foreach (immutable suit; [EnumMembers!Suit])
writefln("%s: %d", suit, suit);
}
But keep in mind that too has a trap:
void main() {
import std.stdio, std.traits;
enum Suit { spades = 0, hearts = 1, diamonds = 1, clubs = 2 }
foreach (immutable suit; [EnumMembers!Suit])
writefln("%s: %d", suit, suit);
}
Prints:
spades: 0
hearts: 1
hearts: 1
clubs: 2
There are cases where the supposed "strong typing" of D is a joke :-) Try to do the same things with Ada enumerations.
Bye,
bearophile
|
December 08, 2013 Re: iterate over enum name:value pairs | ||||
---|---|---|---|---|
| ||||
Posted in reply to bearophile | Thanks. This is exactly what I was looking for. I tried this iteration below, based on the example shown in the std.traits documentation, and the int values are not what I expected, but your example works fine. http://dlang.org/phobos/std_traits.html#.EnumMembers import std.traits; void main() { enum Suit { spades, hearts=4, diamonds=10, clubs } foreach (i, member; EnumMembers!Suit) { writefln("%s: %d", member, i); } } D:\dprojects\ConsoleApp1\ConsoleApp1>dmd -run main.d spades: 0 hearts: 1 diamonds: 2 clubs: 3 but the same example, substituting writefln("%s: %d", member, member) prints D:\dprojects\ConsoleApp1\ConsoleApp1>dmd -run main.d spades: 0 hearts: 4 diamonds: 10 clubs: 11 |
December 08, 2013 Re: iterate over enum name:value pairs | ||||
---|---|---|---|---|
| ||||
Posted in reply to Jay Norwood | Jay Norwood:
> enum Suit { spades, hearts=4, diamonds=10, clubs }
>
> foreach (i, member; EnumMembers!Suit)
Here 'i' is the index of the enumeration type tuple.
This code lacks the [] I added in my code, so your foreach is a static one. To tell them apart when I read the code I sometimes add a comment:
/*static*/ foreach (i, member; EnumMembers!Suit)
Bye,
bearophile
|
December 08, 2013 Re: iterate over enum name:value pairs | ||||
---|---|---|---|---|
| ||||
Posted in reply to bearophile | I see comments about enums being somehow implemented as tuples, and comments about tuples somehow being implemented as structs, but I couldn't find examples of static initialization of arrays of either. Finally after playing around with it for a while, it appears this example below works for static array of struct initialization. It also doesn't display the enum bug of hearts2 coming back as hearts in the iteration. I tried C static array of struct initialization syntax, and it didn't work, which kind of surprises me. module main; import std.stdio; void main() { struct Suit {string nm; int val;}; static Suit[5] suits = [ Suit("spades",1), Suit("hearts",4), Suit("hearts2",4), Suit("diamonds",10), Suit("clubs",11) ]; foreach (member; suits) { writefln("%s: %d", member.nm, member.val); } } D:\dprojects\ConsoleApp1\ConsoleApp1>dmd -run main.d spades: 1 hearts: 4 hearts2: 4 diamonds: 10 clubs: 11 |
December 08, 2013 Re: iterate over enum name:value pairs | ||||
---|---|---|---|---|
| ||||
Posted in reply to Jay Norwood | Jay Norwood: > I see comments about enums being somehow implemented as tuples, Enums are usually implemented as ints, unless you specify a different type. > and comments about tuples somehow being implemented as structs, Phobos Tuples are implemented with structs. > but I couldn't find examples of static initialization of arrays of either. Here it is: import std.typecons; enum Foo { A, B, C } Foo[] a1 = [Foo.A, Foo.B]; alias T = Tuple!(int, int); T[] a1 = [T(1, 2), T(3, 4)]; void main() {} > It also doesn't display the enum bug of hearts2 coming back as hearts in the iteration. Because those are different strings. > I tried C static array of struct initialization syntax, and it didn't work, which kind of surprises me. Here it is: void main() { static struct Suit { string nm; int val; } static Suit[5] suits = [ {"spades", 1}, {"hearts", 4}]; } Bye, bearophile |
December 08, 2013 Re: iterate over enum name:value pairs | ||||
---|---|---|---|---|
| ||||
Posted in reply to bearophile | Yes, thanks, that syntax does work for the initialization. The C syntax that failed for me was using the curly brace form shown in the following link. http://www.c4learn.com/c-programming/c-initializing-array-of-structure/ Also, I think I was trying forms of defining the struct and initializing the array in the same line... something like this C: static struct Suit{ int i; long lv;} suits[3] = {{1, 2L},{2, 4L},{3,9L}}; It looks to me like D requires a named struct definition in a separate line from the array definition. If that is so, then the C initialization of an array with an unnamed struct type, like this, would require a struct type name. static struct { int i; long lv;} suits[3] = {{1, 2L},{2, 4L},{3,9L}}; So, from your static intialization example, this works. Also, the conversion of struct to tuple makes the writefln tupleof conversion on the struct a little cleaner, since you only have to specify the single tuple parameter. module main; import std.stdio; void main() { struct Suit {string nm; int val; int val2; string shortNm;}; static Suit[5] suits = [ {"spades",1,6,"spd"}, {"hearts",4,10,"hrt"}, {"hearts2",4,10,"hrt2"}, {"diamonds",10,16,"dmd"}, {"clubs",11,17,"clb"} ]; foreach (member; suits) { auto tup = member.tupleof; writefln("%s %d %d %s", tup); } } prints spades 1 6 spd hearts 4 10 hrt hearts2 4 10 hrt2 diamonds 10 16 dmd clubs 11 17 clb I also tried using writefln(tup) and writeln(tup) in the example above. The output from writeln(tup) looks like it is headed in the right direction. Maybe a writecsv(tup) would be useful. spades16spd hearts410hrt hearts2410hrt2 diamonds1016dmd clubs1117clb |
December 08, 2013 Re: iterate over enum name:value pairs | ||||
---|---|---|---|---|
| ||||
Posted in reply to Jay Norwood | Jay Norwood: > If that is so, then the C initialization of an array with an unnamed struct type, like this, would require a struct type name. > > static struct { int i; long lv;} suits[3] = {{1, 2L},{2, 4L},{3,9L}}; Giving a struct a name is often a good idea. But if you don't want to name it, then you can use a Phobos Tuple. You can even omit its field names if you want. > struct Suit {string nm; int val; int val2; string shortNm;}; Better: static struct Suit {string nm; int val; int val2; string shortNm;} Generally inside functions it's better to define static struct. And struct definitions don't need a trailing semicolon. > foreach (member; suits) Generally it's better to attach an 'immutable' there, this is not always possible, but it's a good habit: foreach (immutable member; suits) > I also tried using writefln(tup) and writeln(tup) in the example above. The output from writeln(tup) looks like it is headed in the right direction. Maybe a writecsv(tup) would be useful. Try: member.writeln; Bye, bearophile |
December 08, 2013 Re: iterate over enum name:value pairs | ||||
---|---|---|---|---|
| ||||
Posted in reply to bearophile | > foreach (immutable member; suits)
Sometimes you have to use:
foreach (const member; suits)
Bye,
bearophile
|
December 09, 2013 Re: iterate over enum name:value pairs | ||||
---|---|---|---|---|
| ||||
Posted in reply to bearophile | On Sunday, 8 December 2013 at 22:30:25 UTC, bearophile wrote:
>
> Try:
>
> member.writeln;
>
> Bye,
> bearophile
yeah, that's pretty nice.
module main;
import std.stdio;
void main()
{
struct Suit {string nm; int val; int val2; string shortNm;};
static Suit[5] suits = [
{"spades",1,6,"spd"},
{"hearts",4,10,"hrt"},
{"hearts2",4,10,"hrt2"},
{"diamonds",10,16,"dmd"},
{"clubs",11,17,"clb"}
];
foreach (immutable member; suits)
{
member.writeln();
}
}
output:
immutable(Suit)("spades", 1, 6, "spd")
immutable(Suit)("hearts", 4, 10, "hrt")
immutable(Suit)("hearts2", 4, 10, "hrt2")
immutable(Suit)("diamonds", 10, 16, "dmd")
immutable(Suit)("clubs", 11, 17, "clb")
|
Copyright © 1999-2021 by the D Language Foundation