January 29, 2014
On Wednesday, 29 January 2014 at 21:18:06 UTC, Etienne wrote:
>>
>> void exec(string command)(){
>> 	foreach(str ; choice.splitter(".")){
>> 		writeln(str);
>> 	}
>> }
>
> I'd like to take the opportunity to say how much I'd love to be able to do a static foreach rather than use recursion.

You can use TypeTuple for static foreach.

void foo(int x)()
{
	import std.stdio;
	writeln(x);
}

void main()
{
	import std.typetuple;
	foreach (x; TypeTuple!(1, 2, 3))
		foo!x();
}

Notice that the loop variable x is used as a template parameter at compile time. The code expands to:

foo!1();
foo!2();
foo!3();
January 29, 2014
On Wednesday, 29 January 2014 at 07:02:00 UTC, Andrei Alexandrescu wrote:
> On 1/28/14 4:14 PM, bearophile wrote:
>> This is not an enhancement request, but it presents a potential
>> enhancement.
>>
>>
>> This is C++11 code:
>>
>> template<int... digits> struct value;
>>
>> template<> struct value<> {
>>     static const int v = 0;
>> };
>>
>> template<int first, int... rest> struct value<first, rest...> {
>>     static int const v = 10 * value<rest...>::v + first;
>> };
>>
>>
>>
>> You can translate it to D like this:
>>
>>
>> enum isInt(T) = is(T == int);
>>
>> template value(xs...) if (allSatisfy!(isInt, xs)) {
>>     static if (xs.length == 0)
>>         enum value = 0;
>>     else
>>         enum value = xs[0] + 10 * value!(xs[1 .. $]);
>> }
>
> int value(int xs[]...) {
>   int result = 0;
>   foreach (i; xs) {
> 	result += 10 * result + i;
>   }
>   return result;
> }
>
> unittest
> {
>   static assert(value(1, 2) == 21);
> }
>
>
> Andrei

This allocates memory and as such an inferior solution. I'd prefer ugly code over this any day.
January 29, 2014
On Wednesday, 29 January 2014 at 22:25:45 UTC, inout wrote:
>> int value(int xs[]...) {
>>  int result = 0;
>>  foreach (i; xs) {
>> 	result += 10 * result + i;
>>  }
>>  return result;
>> }
>>
>> unittest
>> {
>>  static assert(value(1, 2) == 21);
>> }
>>
>>
>> Andrei
>
> This allocates memory

no
January 30, 2014
On Wednesday, 29 January 2014 at 22:16:57 UTC, Peter Alexander wrote:
> On Wednesday, 29 January 2014 at 21:18:06 UTC, Etienne wrote:
>>>
>>> void exec(string command)(){
>>> 	foreach(str ; choice.splitter(".")){
>>> 		writeln(str);
>>> 	}
>>> }
>>
>> I'd like to take the opportunity to say how much I'd love to be able to do a static foreach rather than use recursion.
>
> You can use TypeTuple for static foreach.
>
> void foo(int x)()
> {
> 	import std.stdio;
> 	writeln(x);
> }
>
> void main()
> {
> 	import std.typetuple;
> 	foreach (x; TypeTuple!(1, 2, 3))
> 		foo!x();
> }
>
> Notice that the loop variable x is used as a template parameter at compile time. The code expands to:
>
> foo!1();
> foo!2();
> foo!3();

Two problems:

1) You can't use `foreach` outside functions. That means that you write:
    struct Foo{
        foreach(i;TypeTuple!(1,2,3)){
            mixin("int num"~i.stringof~";");
        }
    }

2) `foreach` creates it's own scope. This won't work:
    foreach(i; TypeTuple!(1,2,3)){
        mixin("int num"~i.stringof~";");
    }
    num1=1;
    num2=2;
    num3=3;
    writeln(num1,num2,num3);
January 30, 2014
On Thursday, 30 January 2014 at 11:19:33 UTC, Idan Arye wrote:
> On Wednesday, 29 January 2014 at 22:16:57 UTC, Peter Alexander wrote:
>> On Wednesday, 29 January 2014 at 21:18:06 UTC, Etienne wrote:
>>>>
>>>> void exec(string command)(){
>>>> 	foreach(str ; choice.splitter(".")){
>>>> 		writeln(str);
>>>> 	}
>>>> }
>>>
>>> I'd like to take the opportunity to say how much I'd love to be able to do a static foreach rather than use recursion.
>>
>> You can use TypeTuple for static foreach.
>>
>> void foo(int x)()
>> {
>> 	import std.stdio;
>> 	writeln(x);
>> }
>>
>> void main()
>> {
>> 	import std.typetuple;
>> 	foreach (x; TypeTuple!(1, 2, 3))
>> 		foo!x();
>> }
>>
>> Notice that the loop variable x is used as a template parameter at compile time. The code expands to:
>>
>> foo!1();
>> foo!2();
>> foo!3();
>
> Two problems:
>
> 1) You can't use `foreach` outside functions. That means that you write:
>     struct Foo{
>         foreach(i;TypeTuple!(1,2,3)){
>             mixin("int num"~i.stringof~";");
>         }
>     }
>
> 2) `foreach` creates it's own scope. This won't work:
>     foreach(i; TypeTuple!(1,2,3)){
>         mixin("int num"~i.stringof~";");
>     }
>     num1=1;
>     num2=2;
>     num3=3;
>     writeln(num1,num2,num3);

1) You can use mixin(format("<Prolog>%(<Begin>%s<End>%)<Epilog>", CompileTimeRange)); See std.format for ranges and std.string.format.

2) no. This should work for compile time foreach and TypeTuples. There are many examples in source code of Phobos.
January 30, 2014
On Wednesday, 29 January 2014 at 22:16:57 UTC, Peter Alexander wrote:
> You can use TypeTuple for static foreach.
>
> ...

This is why I think using term "declaration foreach" is less confusing. It is pretty much the same but shifts attention away from essentional use case.
January 30, 2014
On 01/30/2014 03:08 PM, Ilya Yaroshenko wrote:
>>
>> 2) `foreach` creates it's own scope. This won't work:
>>     foreach(i; TypeTuple!(1,2,3)){
>>         mixin("int num"~i.stringof~";");
>>     }
>>     num1=1;
>>     num2=2;
>>     num3=3;
>>     writeln(num1,num2,num3);
>
> ...
> 2) no. This should work for compile time foreach and TypeTuples. There
> are many examples in source code of Phobos.

The following code fails to compile:

import std.typetuple, std.stdio;
void main(){
    foreach(i; TypeTuple!(1,2,3)){
        mixin("int num"~i.stringof~";");
    }
    num1=1;
    num2=2;
    num3=3;
    writeln(num1,num2,num3);
}


January 30, 2014
On 2014-01-30 10:28 AM, Timon Gehr wrote:
> import std.typetuple, std.stdio;
> void main(){
>      foreach(i; TypeTuple!(1,2,3)){
>          mixin("int num"~i.stringof~";");
>      }
>      num1=1;
>      num2=2;
>      num3=3;
>      writeln(num1,num2,num3);
> }
>
>

This written as a static foreach or declarative foreach, would be awesome if it exposed the scope. For now the only solution is to build a string and mixin the string like this

string fct(R)(){
	string str;
	foreach (range ; R)
		str ~= "int num " ~ range.stringof ~ ";";

	return str;
}

mixin(fct!(TypeTuple!(1,2,3));
writeln(num1,num2, num3);

Looks a little less convenient than

static foreach ( i; 0..3 )
	mixin("int num" ~ i.stringof ~ ";");
writeln(num1,num2, num3);
January 30, 2014
On Thursday, 30 January 2014 at 15:28:34 UTC, Timon Gehr wrote:
> On 01/30/2014 03:08 PM, Ilya Yaroshenko wrote:
>>>
>>> 2) `foreach` creates it's own scope. This won't work:
>>>    foreach(i; TypeTuple!(1,2,3)){
>>>        mixin("int num"~i.stringof~";");
>>>    }
>>>    num1=1;
>>>    num2=2;
>>>    num3=3;
>>>    writeln(num1,num2,num3);
>>
>> ...
>> 2) no. This should work for compile time foreach and TypeTuples. There
>> are many examples in source code of Phobos.
>
> The following code fails to compile:
>
> import std.typetuple, std.stdio;
> void main(){
>     foreach(i; TypeTuple!(1,2,3)){
>         mixin("int num"~i.stringof~";");
>     }
>     num1=1;
>     num2=2;
>     num3=3;
>     writeln(num1,num2,num3);
> }

I am wrong, foreach always has own scope

    foreach(S; TypeTuple!(string, wstring, dstring))
    {
        import std.conv : to;
        S a = " a     bcd   ef gh ";
        assert(equal(splitter(a), [to!S("a"), to!S("bcd"), to!S("ef"), to!S("gh")]));
        a = "";
        assert(splitter(a).empty);
    }


You can use mixin and format instead:

import std.typetuple, std.stdio;
void main(){
    mixin(format("%(int num%s; %);", [1,2,3])); //<----
    num1=1;
    num2=2;
    num3=3;
    writeln(num1,num2,num3);
}

January 30, 2014
On Thursday, 30 January 2014 at 17:12:51 UTC, Etienne wrote:
> On 2014-01-30 10:28 AM, Timon Gehr wrote:
>> import std.typetuple, std.stdio;
>> void main(){
>>     foreach(i; TypeTuple!(1,2,3)){
>>         mixin("int num"~i.stringof~";");
>>     }
>>     num1=1;
>>     num2=2;
>>     num3=3;
>>     writeln(num1,num2,num3);
>> }
>>
>>
>
> This written as a static foreach or declarative foreach, would be awesome if it exposed the scope. For now the only solution is to build a string and mixin the string like this
>
> string fct(R)(){
> 	string str;
> 	foreach (range ; R)
> 		str ~= "int num " ~ range.stringof ~ ";";
>
> 	return str;
> }
>
> mixin(fct!(TypeTuple!(1,2,3));
> writeln(num1,num2, num3);
>
> Looks a little less convenient than
>
> static foreach ( i; 0..3 )
> 	mixin("int num" ~ i.stringof ~ ";");
> writeln(num1,num2, num3);

It works now:
    mixin(format("%(int num%s; %);", [1,2,3])); //<----
    writeln(num1,num2,num3);