www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - static foreach issues

reply Psychological Cleanup <Help Saving.World> writes:
Nesting static foreach and using enum has latent 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.

So there is no way out of this conundrum? Maybe we need static {}?
Sep 05 2017
next sibling parent reply =?UTF-8?Q?Ali_=c3=87ehreli?= <acehreli yahoo.com> writes:
On 09/05/2017 07:05 PM, Psychological Cleanup wrote:
 Nesting static foreach and using enum has latent problem.

 static foreach()
   static foreach()
   {
      enum A = ;
   }

 compiler complains because A is defined multiple times by the outer most
 foreach.
That's understandable as there are multiple As dropped into code.
 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.
Can you demonstrate with compilable code? Doing what you describe works for me: void main() { static foreach(i; 0 .. 3) static foreach(j; 0 .. 3) { { enum A = i * j; } } } Ali
Sep 05 2017
parent Psychological Cleanup <Help Saving.World> writes:
On Wednesday, 6 September 2017 at 05:23:47 UTC, Ali Çehreli wrote:
 On 09/05/2017 07:05 PM, Psychological Cleanup wrote:
 Nesting static foreach and using enum has latent problem.

 static foreach()
   static foreach()
   {
      enum A = ;
   }

 compiler complains because A is defined multiple times by the
outer most
 foreach.
That's understandable as there are multiple As dropped into code.
 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.
Can you demonstrate with compilable code? Doing what you describe works for me: void main() { static foreach(i; 0 .. 3) static foreach(j; 0 .. 3) { { enum A = i * j; } } } Ali
Yes, but I said you can't do that. Put the static foreaches outside main in to a block where one can't simply do {} and it be valid. You see, the point is that static foreach static foreach { } works at the module level static foreach static foreach { enum a = ; } fails because of multiple a's so static foreach static foreach { { enum a = ; } } to solve that(which, in your given example, works inside main) but fails at the module scope because the { }'s we used to solve the first problem created a new problem. The two methods are mutually exclusive but both are required. Sure, I could wrap stuff around a function, but what if I'm using them for code generation inside a class? I have to use the extra { } to prevent the enum error but then I get a new error about the { }. class X { static foreach static foreach { // fails, multiple a enum a = ; // part of class generation code like generating functions } } class X { static foreach static foreach { // fails, { } block inside a class. { enum a = ; // part of class generation code like generating functions } } } it works fine if we use it in a function because we can have { } in functions without problems. Do you not see the contradictory nature? { } required but { } forbidden.
Sep 05 2017
prev sibling parent Timon Gehr <timon.gehr gmx.ch> writes:
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.) - ...
Sep 06 2017