digitalmars.D - static foreach issues
- Psychological Cleanup (19/19) Sep 05 2017 Nesting static foreach and using enum has latent problem.
- =?UTF-8?Q?Ali_=c3=87ehreli?= (14/32) Sep 05 2017 Can you demonstrate with compilable code? Doing what you describe works
- Psychological Cleanup (58/97) Sep 05 2017 Yes, but I said you can't do that. Put the static foreaches
- Timon Gehr (54/81) Sep 06 2017 Nesting static foreach just works:
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
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
On Wednesday, 6 September 2017 at 05:23:47 UTC, Ali Çehreli wrote:On 09/05/2017 07:05 PM, Psychological Cleanup wrote: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.Nesting static foreach and using enum has latent problem. static foreach() static foreach() { enum A = ; } compiler complains because A is defined multiple times by theouter mostforeach.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 scopewherenormal {}'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
On 06.09.2017 04:05, Psychological Cleanup wrote:Nesting static foreachNesting 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