Jump to page: 1 2
Thread overview
Static foreach.
Nov 02, 2006
Walter Bright
Nov 03, 2006
Bill Baxter
Nov 03, 2006
Walter Bright
Nov 03, 2006
Nick
Nov 04, 2006
Walter Bright
Nov 04, 2006
Nick
Nov 04, 2006
Kirk McDonald
Nov 07, 2006
Russ Lewis
November 02, 2006
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


November 02, 2006
"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.


November 02, 2006
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.
November 03, 2006
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
November 03, 2006
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.
November 03, 2006
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
November 04, 2006
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.
November 04, 2006
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
November 04, 2006
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
November 07, 2006
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.
« First   ‹ Prev
1 2