digitalmars.D.learn - foreach over string enum
- Nrgyzer (11/11) Feb 10 2011 Hey guys,
- Jesse Phillips (12/27) Feb 10 2011 I'll just be leaving this here, if you need more explanation ask, but ma...
- Nrgyzer (10/37) Feb 10 2011 pipermail/
- spir (7/34) Feb 10 2011 Why the mixin? Is it (just) to have the output string computed at compil...
- Jesse Phillips (10/23) Feb 10 2011 The value of 'a' is the enum field name, not its value. The code will ul...
- spir (33/46) Feb 10 2011 Oops! missed this point ;-) Thanks for the explanation, Jesse.
- =?UTF-8?B?QWxpIMOHZWhyZWxp?= (6/12) Feb 10 2011 It works if you define s as:
- spir (7/19) Feb 10 2011 Thank you, Ali.
- Jesse Phillips (5/7) Feb 10 2011 Magic.
- spir (10/17) Feb 11 2011 Oh yes, I see. This explains why my example using plain constants (prede...
- Daniel Murphy (31/35) Feb 20 2011 Actually this happens because __traits(allMembers ...) returns a TypeTup...
Hey guys, I'm trying to iterate over an enumeration which contains strings like the this: enum FileName : string { file1 = "file1.ext", file2 = "file2.ext" } I already found this article: http://lists.puremagic.com/pipermail/ digitalmars-d/2007-July/021920.html but it's an enum which contains integers instead of strings, thus I can't use min- or max-property. Any suggestions -> thanks in advance!
Feb 10 2011
Nrgyzer Wrote:Hey guys, I'm trying to iterate over an enumeration which contains strings like the this: enum FileName : string { file1 = "file1.ext", file2 = "file2.ext" } I already found this article: http://lists.puremagic.com/pipermail/ digitalmars-d/2007-July/021920.html but it's an enum which contains integers instead of strings, thus I can't use min- or max-property. Any suggestions -> thanks in advance!I'll just be leaving this here, if you need more explanation ask, but maybe you'll understand: import std.stdio; enum FileName : string { file1 = "file1.ext", file2 = "file2.ext" } void main(string args[]) { foreach(a; __traits(allMembers, FileName)) writeln(mixin("FileName." ~ a)); }
Feb 10 2011
== Auszug aus Jesse Phillips (jessekphillips+D gmail.com)'s ArtikelNrgyzer Wrote:likeHey guys, I'm trying to iterate over an enumeration which contains stringspipermail/the this: enum FileName : string { file1 = "file1.ext", file2 = "file2.ext" } I already found this article: http://lists.puremagic.com/containsdigitalmars-d/2007-July/021920.html but it's an enum whichproperty.integers instead of strings, thus I can't use min- or max-but maybe you'll understand:Any suggestions -> thanks in advance!I'll just be leaving this here, if you need more explanation ask,import std.stdio; enum FileName : string { file1 = "file1.ext", file2 = "file2.ext" } void main(string args[]) { foreach(a; __traits(allMembers, FileName)) writeln(mixin("FileName." ~ a)); }I've already worked with the mixin-statement, but the __trait is new. As I can see in the documentation, it provides some interesting features. Your solution works great, thanks!
Feb 10 2011
On 02/10/2011 08:22 PM, Jesse Phillips wrote:Nrgyzer Wrote:Why the mixin? Is it (just) to have the output string computed at compile-time? Denis -- _________________ vita es estrany spir.wikidot.comHey guys, I'm trying to iterate over an enumeration which contains strings like the this: enum FileName : string { file1 = "file1.ext", file2 = "file2.ext" } I already found this article: http://lists.puremagic.com/pipermail/ digitalmars-d/2007-July/021920.html but it's an enum which contains integers instead of strings, thus I can't use min- or max-property. Any suggestions -> thanks in advance!I'll just be leaving this here, if you need more explanation ask, but maybe you'll understand: import std.stdio; enum FileName : string { file1 = "file1.ext", file2 = "file2.ext" } void main(string args[]) { foreach(a; __traits(allMembers, FileName)) writeln(mixin("FileName." ~ a)); }
Feb 10 2011
spir Wrote:On 02/10/2011 08:22 PM, Jesse Phillips wrote:The value of 'a' is the enum field name, not its value. The code will ultimately expand to: void main() { writeln(FileName.file1)); writeln(FileName.file2)); } Which in turn will may have its enum contents expanded to the string value. The mixin is required because it is a named enum and 'a' is a string, not an alias: writeln(FileName.a) doesn't work and nor does: writeln(FileName.mixin(a));enum FileName : string { file1 = "file1.ext", file2 = "file2.ext" } void main(string args[]) { foreach(a; __traits(allMembers, FileName)) writeln(mixin("FileName." ~ a)); }Why the mixin? Is it (just) to have the output string computed at compile-time?
Feb 10 2011
On 02/10/2011 11:32 PM, Jesse Phillips wrote:Oops! missed this point ;-) Thanks for the explanation, Jesse. This gave me the opportunity to ask about a detail. The following cannot compile because an argument to string mixin must be a (compile-time) constant: unittest { auto i = 1; auto s = "i"; writeln(mixin("i")); // compiler happy up to here --> "1" writeln(mixin(s)); // compiler unhappy --> "Error: argument to mixin // must be a string, not (s)" } But in your example the symbol a does not look like a constant, instead it the loop variable. Do, how does it work? Or is it that the compiler is able to (1) detect that the collection beeing traversed (__traits(allMembers, FileName)) is a compile-time constant (2) unroll the loop so as to rewrite it first as: foreach(a; ["file1", "file2"]) writeln(mixin("FileName." ~ a)); // *** and then as: writeln(FileName.file1); writeln(FileName.file2); But this doesn't work, neither: auto xx=1, yy=2; auto as = ["x","y"]; foreach(a; as) writeln(mixin(a ~ a)); And in fact the line *** is laso not accepted. So, finally, I understand your code, but not how the compiler processes it so as to see it as a mixin with constant argument. Denis -- _________________ vita es estrany spir.wikidot.comThe value of 'a' is the enum field name, not its value.enum FileName : string {> file1 = "file1.ext", > file2 = "file2.ext" > } > > void main(string args[]) > { > foreach(a; __traits(allMembers, FileName)) > writeln(mixin("FileName." ~ a)); > }Why the mixin? Is it (just) to have the output string computed at compile-time?
Feb 10 2011
I don't have answers to your other questions. On 02/10/2011 03:25 PM, spir wrote:unittest { auto i = 1; auto s = "i";It works if you define s as: enum s = "i";writeln(mixin("i")); // compiler happy up to here --> "1" writeln(mixin(s)); // compiler unhappy --> "Error: argument to mixin // must be a string, not (s)"It now works. Ali
Feb 10 2011
On 02/11/2011 01:02 AM, Ali Çehreli wrote:I don't have answers to your other questions. On 02/10/2011 03:25 PM, spir wrote:Thank you, Ali. denis -- _________________ vita es estrany spir.wikidot.comunittest { auto i = 1; auto s = "i";It works if you define s as: enum s = "i";writeln(mixin("i")); // compiler happy up to here --> "1" writeln(mixin(s)); // compiler unhappy --> "Error: argument to mixin // must be a string, not (s)"It now works. Ali
Feb 10 2011
spir Wrote:But in your example the symbol a does not look like a constant, instead it the loop variable. Do, how does it work?Magic. No really, the best I can tell is that the compiler will try to run the foreach loop at compile-time if there is something in the body that must be evaluated at compile time. The type you are iterating over must be known at compile-time, and just like any such value it is identified by its type and not its contents. So your array literal could in fact be built with a variable, the fact that it is not doesn't matter. I'm not sure if much thought has gone into compile-time-looping, the best way to enforce it is to get a function to run at compile time. I think the rule of "when the body needs evaluated at compile-time" is what's used, but this also means that when you try to iterate something like __traits or tupleof and don't use a compile-time construct in the body, you don't get an error or the loop executed.
Feb 10 2011
On 02/11/2011 05:27 AM, Jesse Phillips wrote:spir Wrote:Oh yes, I see. This explains why my example using plain constants (predefined values, thus known at compile-time) does not run: there is nothing /forcing/ the compiler (such as a ref to a type), thus the compiler does not even try. Even if would be less complicated, probably, than with __traits. Denis -- _________________ vita es estrany spir.wikidot.comBut in your example the symbol a does not look like a constant, instead it the loop variable. Do, how does it work?Magic. No really, the best I can tell is that the compiler will try to run the foreach loop at compile-time if there is something in the body that must be evaluated at compile time. The type you are iterating over must be known at compile-time, and just like any such value it is identified by its type and not its contents. So your array literal could in fact be built with a variable, the fact that it is not doesn't matter. I'm not sure if much thought has gone into compile-time-looping, the best way to enforce it is to get a function to run at compile time. I think the rule of "when the body needs evaluated at compile-time" is what's used, but this also means that when you try to iterate something like __traits or tupleof and don't use a compile-time construct in the body, you don't get an error or the loop executed.
Feb 11 2011
"Jesse Phillips" <jessekphillips+D gmail.com> wrote in message news:ij2drt$1mq3$1 digitalmars.com...Magic. No really, the best I can tell is that the compiler will try to run the foreach loop at compile-time if there is something in the body that must be evaluated at compile time.Actually this happens because __traits(allMembers ...) returns a TypeTuple of string literals. TypeTuples can contain elements of different types (and types themselves as elements), so in order for them to be used in foreach loops, they MUST be unrolled. It's not something in the body, it's the iterable itself that forces unrolling. http://www.digitalmars.com/d/2.0/tuple.html You can do LOTS of cool stuff with this: switch(x) { foreach(i; TypeTuple!(1, 2, 6, 8, 17)) case i: doSomething(); } --------------- class C {} class D : C {} class E : C {} class F : C {} class G : C {} C[] list; foreach(T; TypeTuple!(D, E, F, G)) list ~= new T(); ---------------- int id = runtimeInput(); foreach(i, T; TypeTuple!(C, D ,E, F, G, H)) if (i == id) return new T();
Feb 20 2011