digitalmars.D.learn - foreach over enums?
- %u (12/12) Sep 21 2010 enum X { A=3, B=1, C }
- Simen kjaeraas (9/21) Sep 21 2010 enum X { A=3, B=1, C }
- %u (2/22) Sep 21 2010 D1 :'(
- Simen kjaeraas (22/44) Sep 21 2010 Oh. Without being an expert on D1 matters, I believe that is impossible.
- %u (6/49) Sep 22 2010 Why is this a mixin?
- Simen kjaeraas (51/55) Sep 23 2010 Sorry, it was late and I was tired. Updated code (tested, even! :p):
- %u (3/53) Sep 23 2010 Thanks!! :)
- %u (10/55) Sep 23 2010 Okee, that took me a while to wholly get. :)
- Simen kjaeraas (21/32) Sep 23 2010 It certainly could, and that would explain the presence of 'num', but
- %u (10/40) Sep 23 2010 I thought that would be more annoying to implement(string mixins etc).. ...
- Simen kjaeraas (18/29) Sep 23 2010 They do. There are ways around that - mostly by using string mixins
- %u (8/38) Sep 23 2010 Looking more and more like typecons's defineEnum :)
- Simen kjaeraas (17/32) Sep 23 2010 Impossible in the current version, unless you accept having a bunch of
- Tomek =?UTF-8?B?U293acWEc2tp?= (5/12) Oct 05 2010 mixin("X."~e) => __traits(getMember, X, e)
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 = 3enum 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:D1 :'(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 = 3enum X { A=3, B=1, C } void main( ) { foreach( e; __traits(allMembers, X) ) { writeln( "X.", e, " = ", mixin( "X."~e ) ); } }
Sep 21 2010
%u <e ee.com> wrote:== Quote from Simen kjaeraas (simen.kjaras gmail.com)'s articleOh. 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%u <e ee.com> wrote:D1 :'(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 = 3enum X { A=3, B=1, C } void main( ) { foreach( e; __traits(allMembers, X) ) { writeln( "X.", e, " = ", mixin( "X."~e ) ); } }
Sep 21 2010
== Quote from Simen kjaeraas (simen.kjaras gmail.com)'s article%u <e ee.com> wrote:I think in D1, the foreach need to be encapsulated in a char[] function().== Quote from Simen kjaeraas (simen.kjaras gmail.com)'s articleOh. 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 );" ); }%u <e ee.com> wrote:D1 :'(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 = 3enum X { A=3, B=1, C } void main( ) { foreach( e; __traits(allMembers, X) ) { writeln( "X.", e, " = ", mixin( "X."~e ) ); } }static int opApply( int delegate( ref bar ) dg ) { int result = 0; foreach ( e; T ) { mixin( "result = dg( " ~ e ~ " ) );" );Why is this a mixin?if ( result ) { break; } } return result; } }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.
Sep 22 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
== Quote from Simen kjaeraas (simen.kjaras gmail.com)'s article%u <e ee.com> wrote:Thanks!! :) This I can understand.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 ); } }
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 ); } }Okee, that took me a while to wholly get. :) 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
%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
== Quote from Simen kjaeraas (simen.kjaras gmail.com)'s article%u <e ee.com> wrote:I thought that would be more annoying to implement(string mixins etc).. didn't know it could be that nice :)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[][].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?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?
Sep 23 2010
%u <e ee.com> wrote: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" )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 );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
== Quote from Simen kjaeraas (simen.kjaras gmail.com)'s article%u <e ee.com> wrote:Of course! The encapsulation only needs to string mixin the struct signature.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. "}" }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 );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..Good to know. All this makes for a nice freachable D1 defineEnum, thanks!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.
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 ); }My pleasure. Was a fun challenge. -- SimenGood to know. All this makes for a nice freachable D1 defineEnum, thanks!Won't the compiler even choke on the type size when feedingdefineEnum ahundred 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.
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