static foreach and new identifier names
Adam D. Ruppe
destructionator at gmail.com
Fri Jan 5 17:41:23 UTC 2018
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)
because it expands to
int blargh = 1;
int blargh = 2;
int blargh = 3;
all in the same scope. This makes static foreach of fairly little
value to me - most times I have considered using it, I end up
just using plain old string mixin instead so i can generate names
for the declarations.
Well, how's this for a solution? Any time the compiler is
expecting an identifier in a declaration, it can see the `mixin`
keyword instead and expand that. The mixin expression must yield
a string after passing through ctfe.
import std.conv;
static foreach(foo; [1,2,3]) {
// so freaking ugly. but would now be legal:
int mixin("\"blargh\"" ~ to!string(foo)) = foo;
}
---
int mixin("foo"); // illegal, it returned a symbol foo that
doesn't exist
---
enum foo = "bar";
int mixin("foo"); // now legal, would define `int bar;`
---
int mixin(`"foo"`); // legal, same as `int foo;`
I find this to be pretty freaking hideous... but it is also the
best idea I've had so far to rescue static foreach's value in
making new declarations. It limits the string mixin part to just
the name, I *think* the parser can handle it easily enough, and
it gives all the ctfe flexibility we could use (including outside
static foreach btw).
What do you all think?
ALTERNATIVE IDEA:
Make a special identifier known the compiler, let's call it
`__unique_name` which is unique for any static foreach iteration.
static foreach(foo; [1, 2, 3]) {
int __unique_name = foo;
}
now compiles, since each iteration gives a new magic unique name.
But how do you refer to that in the outside world? With alias:
static foreach(foo; [1, 2, 3]) {
int __unique_name = foo;
mixin("alias " ~ ctfe_generated_name ~ " = __unique_name");
}
In a little example like this, that looks silly, you might as
well just mixin the whole declaration, but for something like a
large function, the mixin remains just that one same alias thing,
while the rest of it is written normally. The alias will then be
responsible for things like merging overloads, if necessary.
More information about the Digitalmars-d
mailing list