static foreach issues

Timon Gehr via Digitalmars-d digitalmars-d at puremagic.com
Wed Sep 6 00:55:08 PDT 2017


On 06.09.2017 04:05, Psychological Cleanup wrote:
> Nesting static foreach

Nesting static foreach just works:

static foreach(i;0..10){
     static foreach(j;0..10){
         pragma(msg, i," ",j);
     }
}

> and using enum has latent problem.
> ...

I'd call it a known limitation. It's not really a problem.

> static foreach()
>    static foreach()
>    {
>       enum A = ;
>    }
> 
> compiler complains because A is defined multiple times by the outer most 
> foreach.
> 
> To fix this
> 
> static foreach()
>    static foreach()
>    {
>       {
>          enum A = ;
>       }
>    }
> 
> But then compiler complains about unexpected { if in a scope where 
> normal {}'s are not expected.
> ...

Nested static foreach is not necessary, this gives the same error:

static foreach(i;0..2){
     enum a = i+2;
}

This code gives an error, as is expected as it expands to

enum a = 2;
enum a = 3;


> So there is no way out of this conundrum? Maybe we need static {}?
> 

Many ways out:

- Use a different name in each iteration.

import std.conv: to;
static foreach(i;0..2){
     mixin("enum a"~to!string(i)~" = i+2;");
     mixin("enum x"~to!string(i)~" = a"~to!string(i)~";");
}



- Parameterize your temporary locals:

template Locals(int i){
     enum a = i+3;
}

static foreach(i;0..2){
     mixin("enum x"~to!string(i)~" = Locals!i.a;");
}


- Use mixin templates to allow multiple definitions of the same name (at 
the cost of disabling overloading):

import std.conv: to;
mixin template Body(int i){
     enum a = i+2;
     mixin("enum x"~to!string(i)~" = a;");
}
static foreach(i;0..2) mixin Body!i;

pragma(msg, x0," ",x1);



Possible language changes to support this use case better:

- Propose a better syntax for the __local feature discussed in the 
"possible future improvements" section of the static foreach DIP, get it 
into the language and use that.

https://github.com/dlang/DIPs/blob/master/DIPs/DIP1010.md

static foreach(i;0..2){
     __local enum a = i+2;
     mixin("enum x"~to!string(i)~" = a;");
}

(I have a working implementation of "__local", but this feature has not 
been added to the language so far.)


- We can think about allowing multiple declarations of the same name 
inside static foreach but then making it local implicitly. (The drawback 
of this is that the first declaration of the symbol is always leaked 
into the outer scope, which is not very clean.)


- ...


More information about the Digitalmars-d mailing list