digitalmars.D.learn - foreach over enums?
- %u <e ee.com> Sep 21 2010
- "Simen kjaeraas" <simen.kjaras gmail.com> Sep 21 2010
- %u <e ee.com> Sep 21 2010
- %u <e ee.com> Sep 22 2010
- %u <e ee.com> Sep 23 2010
- %u <e ee.com> Sep 23 2010
- %u <e ee.com> Sep 23 2010
- %u <e ee.com> Sep 23 2010
- Tomek =?UTF-8?B?U293acWEc2tp?= <just ask.me> Oct 05 2010
- "Simen kjaeraas" <simen.kjaras gmail.com> Sep 21 2010
- "Simen kjaeraas" <simen.kjaras gmail.com> Sep 23 2010
- "Simen kjaeraas" <simen.kjaras gmail.com> Sep 23 2010
- "Simen kjaeraas" <simen.kjaras gmail.com> Sep 23 2010
- "Simen kjaeraas" <simen.kjaras gmail.com> Sep 23 2010
enum X { A=3, B=1, C }
void main() {
foreach(e;X)
writefln(e.stringof," = ",e);
}
//X.A = 3
//X.B = 1
//X.C = 2
or
//X.B = 1
//X.C = 2
//X.A = 3
Sep 21 2010
%u <e ee.com> wrote:enum X { A=3, B=1, C } void main() { foreach(e;X) writefln(e.stringof," = ",e); } //X.A = 3 //X.B = 1 //X.C = 2 or //X.B = 1 //X.C = 2 //X.A = 3
enum X { A=3, B=1, C } void main( ) { foreach( e; __traits(allMembers, X) ) { writeln( "X.", e, " = ", mixin( "X."~e ) ); } } -- Simen
Sep 21 2010
== Quote from Simen kjaeraas (simen.kjaras gmail.com)'s article%u <e ee.com> wrote:enum X { A=3, B=1, C } void main() { foreach(e;X) writefln(e.stringof," = ",e); } //X.A = 3 //X.B = 1 //X.C = 2 or //X.B = 1 //X.C = 2 //X.A = 3
void main( ) { foreach( e; __traits(allMembers, X) ) { writeln( "X.", e, " = ", mixin( "X."~e ) ); } }
D1 :'(
Sep 21 2010
== Quote from Simen kjaeraas (simen.kjaras gmail.com)'s article%u <e ee.com> wrote:== Quote from Simen kjaeraas (simen.kjaras gmail.com)'s article%u <e ee.com> wrote:enum X { A=3, B=1, C } void main() { foreach(e;X) writefln(e.stringof," = ",e); } //X.A = 3 //X.B = 1 //X.C = 2 or //X.B = 1 //X.C = 2 //X.A = 3
void main( ) { foreach( e; __traits(allMembers, X) ) { writeln( "X.", e, " = ", mixin( "X."~e ) ); } }
D1 :'(
I thought there was a struct called defineEnum in phobos1, but it appears I am wrong. However, it should be fairly simple to create one. Untested code, as I do not have D1 installed: struct defineEnum( T... ) { foreach ( i, e; T ) { mixin( "static defineEnum " ~ e ~ " = defineEnum( i );" ); }
static int opApply( int delegate( ref bar ) dg ) { int result = 0; foreach ( e; T ) { mixin( "result = dg( " ~ e ~ " ) );" );
if ( result ) { break; } } return result; } }
what you want it to do (or even how to call it :) Please explain it to me.
Sep 22 2010
== Quote from Simen kjaeraas (simen.kjaras gmail.com)'s article%u <e ee.com> wrote:The code didn't compile, so I tried fixing it.. and failed as I don't really get what you want it to do (or even how to call it :) Please explain it to me.
module foo; import std.stdio; template defineStaticImpl( T, int value, string name, args... ) { mixin( "static T " ~ name ~ " = cast(T)value; " ); static if ( args.length != 0 ) { mixin defineStaticImpl!( T, value + 1, args ); } } template defineStatic( T, args... ) { mixin defineStaticImpl!( T, 0, args ); } struct defineEnum( T... ) { int value; static const int num = T.length; mixin defineStatic!( typeof( this ), T ); static int opApply( int delegate( ref defineEnum ) dg ) { int result = 0; foreach ( i, e; T ) { result = dg( defineEnum( i ) ); if ( result ) { break; } } return result; } static defineEnum opCall( int value ) { defineEnum tmp; tmp.value = value; return tmp; } string toString( ) { foreach ( i, e; T ) { if ( i == value ) { return e.dup; } } } } void main( ) { alias defineEnum!( "A", "B", "C" ) Bar; foreach ( e; Bar ) { writefln( e ); } }
Thanks!! :) This I can understand.
Sep 23 2010
== Quote from Simen kjaeraas (simen.kjaras gmail.com)'s articleSorry, it was late and I was tired. Updated code (tested, even! :p): module foo; import std.stdio; template defineStaticImpl( T, int value, string name, args... ) { mixin( "static T " ~ name ~ " = cast(T)value; " ); static if ( args.length != 0 ) { mixin defineStaticImpl!( T, value + 1, args ); } } template defineStatic( T, args... ) { mixin defineStaticImpl!( T, 0, args ); } struct defineEnum( T... ) { int value; static const int num = T.length; mixin defineStatic!( typeof( this ), T ); static int opApply( int delegate( ref defineEnum ) dg ) { int result = 0; foreach ( i, e; T ) { result = dg( defineEnum( i ) ); if ( result ) { break; } } return result; } static defineEnum opCall( int value ) { defineEnum tmp; tmp.value = value; return tmp; } string toString( ) { foreach ( i, e; T ) { if ( i == value ) { return e.dup; } } } } void main( ) { alias defineEnum!( "A", "B", "C" ) Bar; foreach ( e; Bar ) { writefln( e ); } }
First question, shouldn't the first foreach be replaced by a simple for loop: for(int i = 0; i<num; i++ ) { If I understand it correctly the foreach aggregates are actually string-tuple literals. Then couldn't the second one be CT translated to char[][]? That way the stringOf would be a simple array index. And lastly, I probably need to make the whole struct a string mixin if I want it's type to be like an enum.. don't I? :'(
Sep 23 2010
== Quote from Simen kjaeraas (simen.kjaras gmail.com)'s article%u <e ee.com> wrote:First question, shouldn't the first foreach be replaced by a simple for loop: for(int i = 0; i<num; i++ ) {
it's not necessary, and should make no difference in the generated executable.If I understand it correctly the foreach aggregates are actually string-tuple literals.
Then couldn't the second one be CT translated to char[][]? That way the stringOf would be a simple array index.
exercise for the reader :p. I also thought up a Duff's device-inspired contraption that works: string toString( ) { switch ( value ) { foreach ( i, e; T ) { case i: return T[i]; } } } This should be as fast as the char[][].
know it could be that nice :)And lastly, I probably need to make the whole struct a string mixin if I want it's type to be like an enum.. don't I? :'(
it is it enum-unlike?
These two have distinctly different outputs ;P alias defineEnum!( "A", "B", "C" ) Bar; writefln( typeof(Bar.A).stringof ); enum Foo { A, B, C } writefln( typeof(Foo.A).stringof ); Won't the compiler even choke on the type size when feeding defineEnum a hundred elements or so?
Sep 23 2010
== Quote from Simen kjaeraas (simen.kjaras gmail.com)'s article%u <e ee.com> wrote:I'm not sure what you're getting at here. In what way that you don't like it is it enum-unlike?
These two have distinctly different outputs ;P alias defineEnum!( "A", "B", "C" ) Bar; writefln( typeof(Bar.A).stringof ); enum Foo { A, B, C } writefln( typeof(Foo.A).stringof );
on this form: template defineEnum( string name, T... ) { string defineEnum = "struct " ~ name ~ " {" // Stuff from other implementation goes here. "}" }
mixin( defineEnum!( "EnumName", "A","B","C" ) ); This pattern is one of the reasons I have been lobbying for automatic mixin templates in D2 - it should look only like this: defineEnum!( "EnumName", "A","B","C" )
Looking more and more like typecons's defineEnum :) though, supporting a non-continues range of values (which I don't need) will be annoying in this setup, I think.. but, I think typecons uses the slow if version..Won't the compiler even choke on the type size when feeding defineEnum a hundred elements or so?
elements in this case. If you're thinking of the horribly long names, I believe identifiers are hashed rather than being stored wholesale, once they move past 16K.
All this makes for a nice freachable D1 defineEnum, thanks!
Sep 23 2010
Simen kjaeraas napisaĆ:enum X { A=3, B=1, C } void main( ) { foreach( e; __traits(allMembers, X) ) { writeln( "X.", e, " = ", mixin( "X."~e ) ); } }
mixin("X."~e) => __traits(getMember, X, e) For mixin-allergics. -- Tomek
Oct 05 2010
%u <e ee.com> wrote:== Quote from Simen kjaeraas (simen.kjaras gmail.com)'s article%u <e ee.com> wrote:enum X { A=3, B=1, C } void main() { foreach(e;X) writefln(e.stringof," = ",e); } //X.A = 3 //X.B = 1 //X.C = 2 or //X.B = 1 //X.C = 2 //X.A = 3
void main( ) { foreach( e; __traits(allMembers, X) ) { writeln( "X.", e, " = ", mixin( "X."~e ) ); } }
D1 :'(
Oh. Without being an expert on D1 matters, I believe that is impossible. I thought there was a struct called defineEnum in phobos1, but it appears I am wrong. However, it should be fairly simple to create one. Untested code, as I do not have D1 installed: struct defineEnum( T... ) { foreach ( i, e; T ) { mixin( "static defineEnum " ~ e ~ " = defineEnum( i );" ); } static int opApply( int delegate( ref bar ) dg ) { int result = 0; foreach ( e; T ) { mixin( "result = dg( " ~ e ~ " ) );" ); if ( result ) { break; } } return result; } } -- Simen
Sep 21 2010
%u <e ee.com> wrote:The code didn't compile, so I tried fixing it.. and failed as I don't really get what you want it to do (or even how to call it :) Please explain it to me.
Sorry, it was late and I was tired. Updated code (tested, even! :p): module foo; import std.stdio; template defineStaticImpl( T, int value, string name, args... ) { mixin( "static T " ~ name ~ " = cast(T)value; " ); static if ( args.length != 0 ) { mixin defineStaticImpl!( T, value + 1, args ); } } template defineStatic( T, args... ) { mixin defineStaticImpl!( T, 0, args ); } struct defineEnum( T... ) { int value; static const int num = T.length; mixin defineStatic!( typeof( this ), T ); static int opApply( int delegate( ref defineEnum ) dg ) { int result = 0; foreach ( i, e; T ) { result = dg( defineEnum( i ) ); if ( result ) { break; } } return result; } static defineEnum opCall( int value ) { defineEnum tmp; tmp.value = value; return tmp; } string toString( ) { foreach ( i, e; T ) { if ( i == value ) { return e.dup; } } } } void main( ) { alias defineEnum!( "A", "B", "C" ) Bar; foreach ( e; Bar ) { writefln( e ); } } -- Simen
Sep 23 2010
%u <e ee.com> wrote:First question, shouldn't the first foreach be replaced by a simple for loop: for(int i = 0; i<num; i++ ) {
It certainly could, and that would explain the presence of 'num', but it's not necessary, and should make no difference in the generated executable.If I understand it correctly the foreach aggregates are actually string-tuple literals.
Yes.Then couldn't the second one be CT translated to char[][]? That way the stringOf would be a simple array index.
Indeed it could, though I will leave its implementation as an exercise for the reader :p. I also thought up a Duff's device-inspired contraption that works: string toString( ) { switch ( value ) { foreach ( i, e; T ) { case i: return T[i]; } } } This should be as fast as the char[][].And lastly, I probably need to make the whole struct a string mixin if I want it's type to be like an enum.. don't I? :'(
I'm not sure what you're getting at here. In what way that you don't like it is it enum-unlike? -- Simen
Sep 23 2010
%u <e ee.com> wrote:I'm not sure what you're getting at here. In what way that you don't like it is it enum-unlike?
These two have distinctly different outputs ;P alias defineEnum!( "A", "B", "C" ) Bar; writefln( typeof(Bar.A).stringof ); enum Foo { A, B, C } writefln( typeof(Foo.A).stringof );
They do. There are ways around that - mostly by using string mixins on this form: template defineEnum( string name, T... ) { string defineEnum = "struct " ~ name ~ " {" // Stuff from other implementation goes here. "}" } mixin( defineEnum!( "EnumName", "A","B","C" ) ); This pattern is one of the reasons I have been lobbying for automatic mixin templates in D2 - it should look only like this: defineEnum!( "EnumName", "A","B","C" )Won't the compiler even choke on the type size when feeding defineEnum a hundred elements or so?
Types are limited to 64K of memory, I think. That should be enough for 16K elements in this case. If you're thinking of the horribly long names, I believe identifiers are hashed rather than being stored wholesale, once they move past 16K. -- Simen
Sep 23 2010
%u <e ee.com> wrote:though, supporting a non-continues range of values (which I don't need) will be annoying in this setup, I think..
Impossible in the current version, unless you accept having a bunch of dummy fields. It is not hard to implement: template defineStaticImpl( T, int value, string name ) { // Do as below, no recursion. } template defineStaticImpl( T, int value, string name, string next, args... ) { // Mostly as before. } template defineStaticImpl( T, int value, string name, int actualValue, args... ) { mixin defineStaticImpl!( T, actualValue, name, args ); }Won't the compiler even choke on the type size when feeding
hundred elements or so?
16K elements in this case. If you're thinking of the horribly long names, I believe identifiers are hashed rather than being stored wholesale, once they move past 16K.
All this makes for a nice freachable D1 defineEnum, thanks!
My pleasure. Was a fun challenge. -- Simen
Sep 23 2010









%u <e ee.com> 