Re: foreach over string enum
Jesse Phillips jessekphillip...@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();
Re: foreach over string enum
On 02/11/2011 05:27 AM, Jesse Phillips wrote: 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. 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.com
Re: foreach over string enum
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)); }
Re: foreach over string enum
== Auszug aus Jesse Phillips (jessekphillip...@gmail.com)'s Artikel 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)); } 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!
Re: foreach over string enum
On 02/10/2011 08:22 PM, Jesse Phillips wrote: 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)); } Why the mixin? Is it (just) to have the output string computed at compile-time? Denis -- _ vita es estrany spir.wikidot.com
Re: foreach over string enum
spir Wrote: On 02/10/2011 08:22 PM, Jesse Phillips wrote: 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? 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));
Re: foreach over string enum
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
Re: foreach over string enum
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: 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 Thank you, Ali. denis -- _ vita es estrany spir.wikidot.com
Re: foreach over string enum
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.