On Fri, Jan 05, 2018 at 05:41:23PM +0000, Adam D. Ruppe via Digitalmars-d wrote:
> Y'all know if we write this:
> 
> static foreach(foo; [1,2,3]) {
>         int blargh = foo;
> }
> 
> we get:
> 
> e2.d(2): Error: variable e2.__anonymous.blargh conflicts with variable
> e2.__anonymous.blargh at e2.d(2)
> e2.d(2): Error: variable e2.__anonymous.blargh conflicts with variable
> e2.__anonymous.blargh at e2.d(2)
[...]

Simple solution: add another pair of {} to create a nested scope:

        static foreach(foo; [1,2,3]) {{
                int blargh = foo;
        }}

Well, perhaps this looks just as hideous to your eyes, but at least we
didn't have to resort to mixins. :-D  OTOH, if you actually need to
insert declarations into the containing scope that depends on these
temporary declarations, then this won't work.

I recently ran into a similar issue, not 100% sure whether it should be
considered a bug/enhancement request, but basically:

        static foreach (x; blah) {{
                struct S {
                        ... // declarations that depend on x
                }
                S s;
                ... // do something with s
        }}

Initially, I tried it without the double braces, but of course that
doesn't work because S is declared multiple times with incompatible
definitions.  But even with the double braces, the compiler complained
"identifier S is already declared in another scope". :-(  Apparently,
it's illegal to reuse the same identifier in the same function, even
though each declaration is actually in its own disjoint scope.

Two solutions occurred to me at the time: (1) create a new identifier
namespace with a nested function. I found this far too ugly, so I
ditched the idea. (2) Use a mixin to create new names for each
declaration, which is what you proposed. But that meant putting a lot of
code inside a string, which is extremely ugly (even if D does have token
strings, which alleviated the ugliness a little bit, but only a little
bit).

Then suddenly it struck me: (1) What we need is a way to create new
identifiers that depends on some compile-time entity, like the loop
variable of a static foreach. (2) A template instantiated with some
compile-time entity as argument creates a new, unique name for that
particular template instantiation.  Put these two together, and Bingo!:

        struct S(x) { // or alias x, depending on what x is
                ... // declarations that depend on x
        }

        static foreach (x; blah) {{
                S!x s; // <--- this is the magic right here
                ... // do something with s
        }}

Problem solved. :-D

In your case, you might be able to do something similar:

        struct MyInt(int foo) {
                int blargh = foo;
                alias blargh this;
        }

        static foreach(foo; [1,2,3]) {{
                MyInt!foo blargh;
        }}

alias this FTW!


T

-- 
Tell me and I forget. Teach me and I remember. Involve me and I understand. -- 
Benjamin Franklin

Reply via email to