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

Ethan gooberman at gmail.com
Tue Jun 5 10:11:49 UTC 2018


I've come across this before with Binderoo, but now I've got 
really simple use cases.

Rather than having one unmaintainable mess of a file that handles 
everything (for a really egregious example, see 
std.datetime.systime which has the distinction of both its source 
code and documentation being unreadable), I decided to do 
something similar to C#'s partial classes and use mixin templates 
declared in other modules to complete the implementation.

This is all well and good until you get to dealing with function 
overloads.

Exhibit A: https://run.dlang.io/is/a85Lbq

As soon as you have an overload of a function declared in the 
base object you're mixing in to, any other overload mixed in will 
not resolve correctly. Great.

The core use case I derived this from is client/server message 
handling, and I plan on reusing mixins across client/server types 
since message handling will also require variables added in to 
the object to do so. Simple example: Handling Ping and Pong will 
require the Ping sender to start a timer and resolve it on 
receiving Pong. The partial class model is perfect for this, and 
mixins are the closest we have to this.

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.

Exhibit B: https://run.dlang.io/is/s2BJUO

This one fired as soon as Binderoo tried to do its thing: Doing 
an allMembers pass of the object will list your entirely-mixed-in 
overload as a member, but attempting to get that member will 
resolve the symbol to void.

Great. So functions that otherwise completely resolve as a member 
of a class actually don't resolve as a member of a class? Huh? I 
don't even.

To see where I'm going with this, exhibit C: 
https://run.dlang.io/is/KWN9yA

Rather than mixin things one by one and manually handle errors 
and language shortcomings, I'm using helpers to wholesale add 
functionality to my object.

And, honestly, with this method, I am already seeing the 
workaround. Because I've had to do it a ton of times already with 
other templates. Run a search for 'mixin( "import' in Binderoo to 
see how many times I've had to get around the changes to template 
visibility rules. Rather than do that though, now I'll have to 
iterate over every member of a stored mixin and alias them in to 
the surrounding object.

Sigh.

I know that simply posting this will result in a thread of people 
offering workarounds. I don't need or want them. Why? Because the 
next person that tries to do this will have the same problems. 
And rather than the "correct" way to do this be voodoo knowledge 
found by a Google search if you're lucky, I would far prefer this 
thread become a discussion on how to improve mixins so that a DIP 
can be written and resolved. So that the next person can express 
language as simply as possible and have it all Just Work(TM).


More information about the Digitalmars-d mailing list