static foreach and enum do not play nice together!

import std.meta, std.stdio;
import std.string : leftJustify, center, rightJustify;
alias functions = staticMap!(ApplyRight!(Instantiate, string),
                             leftJustify, center, rightJustify);

void main()
{
        string result = "|";
        static foreach (f; functions)
        {
                enum y = &f;
                // pragma(msg, y("hello", 17));
                mixin("enum z = &"~f~".stringof;");
                pragma(msg, z);
auto x = &f; // not a template, but a function instantiation
                result ~= x("hello", 17);
                result ~= "|";
        }
        writeln(result); // "hello  ; hello ;  hello;
}

Besides the issue of trying to print out information about f at compile time, which is what I was working on here, since the above is a cool way to aggregate similar functions at compile time, I run in to the notorious issue of using enum's in loops!

The enums are local in nature and are used to store intermediate results but the looping tries to redefine them, which gives an error.

Instead, how about having a new type or keyword such as __local than can create a temporary enum that is only valid inside the loop just like a local variable:

void main()
{
        string result = "|";
        static foreach (f; functions)
        {
                __local enum y = &f;
                // pragma(msg, y("hello", 17));
                mixin("__local enum z = &"~f~".stringof;");
                pragma(msg, z);
auto x = &f; // not a template, but a function instantiation
                result ~= x("hello", 17);
                result ~= "|";
        }
        writeln(result); // "hello  ; hello ;  hello;
}

here y and z then are local to the static for each and only exist within it's scope. The compiler then will not error out about redefinitions.

I know this is a trivial example that does not require __local enums but in many cases they are necessary or reduce complexity.


Because I'm nice, I will give a hack that can be used, but this hack should only be used by those who think the compiler shouldn't automatically do this type of stuff for us:

void main()
{
        static foreach (k, f; [113,22,13])
        {
                mixin("enum y"~to!string(k)~" = f;");               
                mixin("pragma(msg, y"~to!string(k)~");");
        }
}

The idea is simply to create a new enum per loop. This is not an acceptable hack but the compiler could do this internally really simple, which is what __local would signify reducing all the overhead and the above is then represented as


void main()
{
        static foreach (f; [113,22,13])
        {
                __local enum y = f;             
                pragma(msg, y);
        }
}

Much nicer and one can imagine how this would simplify a lot of code.

Another, probably better idea is to simply allow enums to be overwritten at compile time:

void main()
{
        venum y;
        static foreach (f; [113,22,13])
        {
                y = f;          
                pragma(msg, y);
        }
}


Reply via email to