Re: foreach over string enum

2011-02-20 Thread Daniel Murphy
"Jesse Phillips"  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

2011-02-11 Thread spir

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

2011-02-10 Thread Jesse Phillips
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.


Re: foreach over string enum

2011-02-10 Thread spir

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

2011-02-10 Thread Ali Çehreli

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

2011-02-10 Thread spir

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



Re: foreach over string enum

2011-02-10 Thread Jesse Phillips
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

2011-02-10 Thread spir

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

2011-02-10 Thread Nrgyzer
== 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

2011-02-10 Thread Jesse Phillips
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));
}