Mixin templates are a pain at best, useless at worst for any non-trivial use case

Simen Kjærås simen.kjaras at gmail.com
Tue Jun 5 12:08:58 UTC 2018


On Tuesday, 5 June 2018 at 10:11:49 UTC, Ethan wrote:
> Exhibit A: https://run.dlang.io/is/a85Lbq
>
> I submitted a bug with the above code, and it was "helpfully" 
> shut down with a link to the documentation and workaround. 
> Congratulations. That's not the use case here, and to be quite 
> honest this is one of those examples where a #define macro 
> would "just work". And I'm firmly of the view that *ANY* 
> example of that should be dealt with at a language level in 
> order to completely remove the argument of needing a 
> preprocessor.

There's a reason for those rules in the language, namely function 
hijacking. This is an issue we take very seriously, and 
workarounds exists.

As you point out, the suggested workaround is aliasing each 
function in the mixin (you also say you don't want workarounds - 
bear with me, I'm building to a point). This can to some extent 
be encapsulated in a string mixin that's used alongside any 
template mixin:

string introduceSymbols(alias F)()
{
     enum id = __traits(identifier, F);
     return "static foreach (fn; __traits(allMembers, "~id~")) {"~
            "    mixin(`alias `~fn~` = "~id~".`~fn~`;`);"~
            "}";
}

mixin foo!() foo_;
mixin(introduceSymbols!foo_);

This introduces complexity in that each mixin must be given a 
unique name at instantiation, another line must be included with 
every mixin, and the name must be repeated in the second line. 
This situation is less than optimal, and the compiler gives no 
help if you've forgotten a introduceSymbols line, or passed it 
the wrong name.

These issues can be ameliorated as in your other post here, by 
wrapping the template mixin statement as well. This leads to a 
host of other problems - how do you specify arguments to the 
mixin template? How do you deal with aliased mixin templates? 
These issues may possibly be fixed, but it's gonna get ugly.


Can we perhaps do better? Could we somehow say at the 
instantiation point 'please introduce all symbols in this mixin 
into the instantiation scope even if there are hijackings.'?  
Something like `mixin scope foo!();`? That seems possible to me. 
If we write a DIP for it, I've a good feeling about getting that 
into the language.

This issue shows up every now and then, so we know it's a real 
issue, and the workarounds are clunky. At the same time, the 
current behavior is there for a reason, and is very unlikely to 
change.

--
   Simen


More information about the Digitalmars-d mailing list