www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Static foreach.

reply "Jarrett Billingsley" <kb3ctd2 yahoo.com> writes:
I am overjoyed by the variadic templates.  This is how variadic functions 
_should_ be, and this opens up so many other possibilities as well.

One of the cooler things is the ability to iterate over a tuple with 
foreach.  So:

void print(T...)(T args)
{
    foreach(arg; args)
        writef(arg);

    writefln();
}

This is great.  DMD even unrolls this loop, making it a sort of "static 
foreach."

But what _else_ could this tuple/foreach facility be used for?

Let's assume the new "foreaching over a tuple" had to be done with "static 
foreach", so the above code would simply have a "static" before the 
"foreach".  Not a large sacrifice to make, and it also makes it explicit 
that the loop is looped at compile time and not at runtime.

Now, since static foreach is no longer a "statement", it can appear where 
statements can't, like inside regular templates.  Then you can iterate over 
Nov 02 2006
next sibling parent reply "Jarrett Billingsley" <kb3ctd2 yahoo.com> writes:
"Jarrett Billingsley" <kb3ctd2 yahoo.com> wrote in message 
news:eidr8f$1atn$1 digitaldaemon.com...

 Now, since static foreach is no longer a "statement", it can appear where 
 statements can't, like inside regular templates.  Then you can iterate 
 over

Huh, who know ctrl+enter posted. In any case, I was trying to come up with examples, but couldn't.. maybe it wouldn't be as useful as I thought.
Nov 02 2006
parent reply Walter Bright <newshound digitalmars.com> writes:
Jarrett Billingsley wrote:
 In any case, I was trying to come up with examples, but couldn't.. maybe it 
 wouldn't be as useful as I thought. 

It is an interesting idea, but I agree we should wait until a compelling use case appears.
Nov 02 2006
next sibling parent reply Bill Baxter <wbaxter gmail.com> writes:
Walter Bright wrote:
 Jarrett Billingsley wrote:
 
 In any case, I was trying to come up with examples, but couldn't.. 
 maybe it wouldn't be as useful as I thought. 

It is an interesting idea, but I agree we should wait until a compelling use case appears.

It's basically a typelist, no? If so you should be able to find lots of examples for how it would be useful. Here's one: http://www.codeproject.com/cpp/TTLTyplist.asp?df=100&forumid=29952&exp=0&select=724784 A variant template. Lets you do something like: typedef variant< my_type, double > mv; You could replace the fixed-maximum number of fields in that code with an unlimited number, and replace all the recursively instatiated typelist code with a straightforward foreach. Basically in C++ every template that processes a typelist has to do so recursively, but with a static foreach you should be able to the same in a more straightforward procedural manner. --bb
Nov 02 2006
parent Walter Bright <newshound digitalmars.com> writes:
Bill Baxter wrote:
 Walter Bright wrote:
 It is an interesting idea, but I agree we should wait until a 
 compelling use case appears.

It's basically a typelist, no?

Yup.
 If so you should be able to find lots of examples for how it would be 
 useful.

I just need to learn about them.
Nov 02 2006
prev sibling parent reply Nick <a bb.com> writes:
Here's a useful example (I think):

void rotLeft(X...)()
{
  typeof(X[0]) tmp = X[0];
  foreach(int i, x; X[1..$])
    X[i] = x;
  X[$-1] = tmp;
}

void main()
{
  int a=1, b=2, c=3;
  rotLeft!(a,b,c); // Should produce a,b,c = 2,3,1
}

Compiling gives the error "Integer constant expression expected instead of i".

I'm using this right now, but instead of being generic, the version I have
contains lots statements like
...
static if(X.length > 2) X[1] = X[2];
static if(X.length > 3) X[2] = X[3];
etc.

Nick
Nov 03 2006
parent reply Walter Bright <newshound digitalmars.com> writes:
Nick wrote:
 Here's a useful example (I think):
 
 void rotLeft(X...)()
 {
   typeof(X[0]) tmp = X[0];
   foreach(int i, x; X[1..$])
     X[i] = x;
   X[$-1] = tmp;
 }
 
 void main()
 {
   int a=1, b=2, c=3;
   rotLeft!(a,b,c); // Should produce a,b,c = 2,3,1
 }
 
 Compiling gives the error "Integer constant expression expected instead of i".
 
 I'm using this right now, but instead of being generic, the version I have
 contains lots statements like
 ...
 static if(X.length > 2) X[1] = X[2];
 static if(X.length > 3) X[2] = X[3];
 etc.

Template tuple parameters aren't function parameters that can be modified. You'll need to pass a, b, c as inout parameters to the function, not the template.
Nov 04 2006
next sibling parent Nick <a bb.com> writes:
WB:
 Template tuple parameters aren't function parameters that can be
 modified. You'll need to pass a, b, c as inout parameters to the
 function, not the template.

I know it is probably not the intended use of tuple parameteres, but it actually does work (the static if version.) The ints that are passed works just like template alias parameters, and so the original values are modified correctly. At least that's what all my tests show. Reading over the docs again I realize that this might actually be an undocumented feature, but I thought it was kinda nifty. Nick
Nov 04 2006
prev sibling parent Kirk McDonald <kirklin.mcdonald gmail.com> writes:
Walter Bright wrote:
 Nick wrote:
 Here's a useful example (I think):

 void rotLeft(X...)()
 {
   typeof(X[0]) tmp = X[0];
   foreach(int i, x; X[1..$])
     X[i] = x;
   X[$-1] = tmp;
 }

 void main()
 {
   int a=1, b=2, c=3;
   rotLeft!(a,b,c); // Should produce a,b,c = 2,3,1
 }

 Compiling gives the error "Integer constant expression expected 
 instead of i".

 I'm using this right now, but instead of being generic, the version I 
 have
 contains lots statements like
 ...
 static if(X.length > 2) X[1] = X[2];
 static if(X.length > 3) X[2] = X[3];
 etc.

Template tuple parameters aren't function parameters that can be modified. You'll need to pass a, b, c as inout parameters to the function, not the template.

Which once again brings up a problem. This doesn't work: void func(T ...)(inout T t) { // ... } Similarly, this doesn't work: void func(T ...)(T t) { foreach(inout arg; t) { // do something with args } // call with modified args other_func(t); } That idiom would be /so useful/. -- Kirk McDonald Pyd: Wrapping Python with D http://pyd.dsource.org
Nov 04 2006
prev sibling parent reply Russ Lewis <spamhole-2001-07-16 deming-os.org> writes:
Jarrett Billingsley wrote:
 void print(T...)(T args)
 {
     foreach(arg; args)
         writef(arg);
 
     writefln();
 }

This looks to me like a good way to do reflection. Imagine that each variable had a property called "members" which returned the tuple of all of the members. Then dumping all of the members of a struct would be as simple as: foreach(member; this.members) writefln(member); Of course, if tuples were extended to include a "name" field, which was the name that was used to access the field, then we'd have everything: foreach(member; this.members) writefln(member.name," ",member); Of course, if we can do this, then we can do almost everything needed for reflection (especially if we are able to take the address of one element of a tuple, and that works out being the pointer to the member in the struct). Tuples aren't there yet, but they're close.
Nov 06 2006
parent "Jarrett Billingsley" <kb3ctd2 yahoo.com> writes:
"Russ Lewis" <spamhole-2001-07-16 deming-os.org> wrote in message 
news:eiolhg$21va$1 digitaldaemon.com...

 This looks to me like a good way to do reflection.  Imagine that each 
 variable had a property called "members" which returned the tuple of all 
 of the members.  Then dumping all of the members of a struct would be as 
 simple as:

   foreach(member; this.members)
     writefln(member);

 Of course, if tuples were extended to include a "name" field, which was 
 the name that was used to access the field, then we'd have everything:

   foreach(member; this.members)
     writefln(member.name," ",member);

 Of course, if we can do this, then we can do almost everything needed for 
 reflection (especially if we are able to take the address of one element 
 of a tuple, and that works out being the pointer to the member in the 
 struct).

 Tuples aren't there yet, but they're close.

Wooooo! That's so tantalizing.
Nov 06 2006