Thread overview | |||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
February 10, 2011 foreach over string enum | ||||
---|---|---|---|---|
| ||||
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! |
February 10, 2011 Re: foreach over string enum | ||||
---|---|---|---|---|
| ||||
Posted in reply to Nrgyzer | 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));
}
|
February 10, 2011 Re: foreach over string enum | ||||
---|---|---|---|---|
| ||||
Posted in reply to Jesse Phillips | == Auszug aus Jesse Phillips (jessekphillips+D@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! |
February 10, 2011 Re: foreach over string enum | ||||
---|---|---|---|---|
| ||||
Posted in reply to Jesse Phillips | 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 |
February 10, 2011 Re: foreach over string enum | ||||
---|---|---|---|---|
| ||||
Posted in reply to spir | 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)); |
February 10, 2011 Re: foreach over string enum | ||||
---|---|---|---|---|
| ||||
Posted in reply to Jesse Phillips | On 02/10/2011 11:32 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. 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.com |
February 11, 2011 Re: foreach over string enum | ||||
---|---|---|---|---|
| ||||
Posted in reply to spir | 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 |
February 11, 2011 Re: foreach over string enum | ||||
---|---|---|---|---|
| ||||
Posted in reply to Ali Çehreli | 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 |
February 11, 2011 Re: foreach over string enum | ||||
---|---|---|---|---|
| ||||
Posted in reply to spir | 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.
|
February 11, 2011 Re: foreach over string enum | ||||
---|---|---|---|---|
| ||||
Posted in reply to Jesse Phillips | 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 |
Copyright © 1999-2021 by the D Language Foundation