Thread overview
template mixins for boilerplate
Jun 21, 2014
Paul D Anderson
Jun 21, 2014
Philippe Sigaud
Jun 21, 2014
Artur Skawina
Jun 21, 2014
Paul D Anderson
Jun 21, 2014
Philippe Sigaud
Jun 21, 2014
Dicebot
Jun 21, 2014
Philippe Sigaud
Jun 21, 2014
Dicebot
Jun 21, 2014
Artur Skawina
Jun 21, 2014
Philippe Sigaud
June 21, 2014
I am misunderstanding something about using mixins for boilerplate code.

I've got a set of functions all of which do the same thing:

public static int fctn1() { return other.place.fctn1; }

I can't use a string mixin to generate the code:

template Function(string name)
{
  const char[] Function =
    "public static int " ~ name ~ "() { return other.place." ~ name ~"; }";
}

struct S {
mixin (Function!("fctn1"));
}

Error: "cannot use a template to add field to aggregate S".

I can't use a template mixin:

mixin template Function(string name)
{
  const char[] Function =
    "public static int " ~ name ~ "() { return other.module." ~ name ~"; }";
}

Error: mixin templates are not regular templates.

Is there a way to duplicate fctn1 with a different name each time?

Paul
June 21, 2014
Use a string mixin?

string fun(string name)
{
  return "public static int " ~ name ~ "() { return 0; }";
}

struct S {
    mixin (fun("fctn1"));
}

void main() {
    S s;
    import std.stdio;
    writeln(s.fctn1());
}
June 21, 2014
On 06/21/14 05:32, Paul D Anderson via Digitalmars-d-learn wrote:
> I can't use a template mixin:
> 
> mixin template Function(string name)
> {
>   const char[] Function =
>     "public static int " ~ name ~ "() { return other.module." ~ name ~"; }";
> }
> 
> Error: mixin templates are not regular templates.

   mixin template Function(string name) {
      mixin("public static int " ~ name ~ "() { return other.module." ~ name ~"; }");
   }

   struct S {
      mixin Function!"fctn1";
   }

artur
June 21, 2014
On Saturday, 21 June 2014 at 11:12:18 UTC, Artur Skawina via Digitalmars-d-learn wrote:
> On 06/21/14 05:32, Paul D Anderson via Digitalmars-d-learn wrote:
>> I can't use a template mixin:
>> 
>> mixin template Function(string name)
>> {
>>   const char[] Function =
>>     "public static int " ~ name ~ "() { return other.module." ~ name ~"; }";
>> }
>> 
>> Error: mixin templates are not regular templates.
>
>    mixin template Function(string name) {
>       mixin("public static int " ~ name ~ "() { return other.module." ~ name ~"; }");
>    }
>
>    struct S {
>       mixin Function!"fctn1";
>    }
>
> artur

Beautiful! That's it.

Thanks,

Paul
June 21, 2014
Out of curiosity, why use a mixin template containing a string mixin instead of, well, directly injecting a string mixin in your struct, with a function?
June 21, 2014
On Saturday, 21 June 2014 at 13:45:14 UTC, Philippe Sigaud via Digitalmars-d-learn wrote:
> Out of curiosity, why use a mixin template containing a string mixin
> instead of, well, directly injecting a string mixin in your struct,
> with a function?

Hiding non-hygienic implementation behind a more reliable interface.
June 21, 2014
On Sat, Jun 21, 2014 at 4:24 PM, Dicebot via Digitalmars-d-learn <digitalmars-d-learn@puremagic.com> wrote:
> On Saturday, 21 June 2014 at 13:45:14 UTC, Philippe Sigaud via Digitalmars-d-learn wrote:
>>
>> Out of curiosity, why use a mixin template containing a string mixin instead of, well, directly injecting a string mixin in your struct, with a function?
>
>
> Hiding non-hygienic implementation behind a more reliable interface.

In what way is a template more reliable than the equivalent function? That's an honest question: I'm just looking at the code a few posts upward:

mixin template Function(string name) {
    mixin("public static int " ~ name ~ "() { return other.module." ~
name ~"; }");
}

struct S {
      mixin Function!"fctn1";
}

And this double-mixin construction seems needlessly complicated to me, compared to:

string Function(string name) {
      return "public static int " ~ name ~ "() { return other.module."
~ name ~"; }";
}

struct S {
    mixin(Function("fctn1"));
}
June 21, 2014
On 06/21/14 18:01, Philippe Sigaud via Digitalmars-d-learn wrote:
> In what way is a template more reliable than the equivalent function?

> mixin template Function(string name) {
>     mixin("public static int " ~ name ~ "() { return other.module." ~
> name ~"; }");
> }
> 
> struct S {
>       mixin Function!"fctn1";
> }
> 
> And this double-mixin construction seems needlessly complicated to me,

It does not make much difference for this simple case, but doing it this
way allows for other declarations that do not need to be mixed in.
IOW if 'Function' contains more boilerplate, then it does not all need
to be written inside a string. Not to mention it saves two sets of parens. :)
A mixin template *is* slightly more reliable than a function, because
it won't be (ab-)usable in many context where a normal function call works.
But I think this choice is mostly an aesthetical (ie subjective) one.

artur
June 21, 2014
I see, thanks Artur.
June 21, 2014
Apart from what Artur has mentioned template mixins also give you opportunity to do qualified injection in case generated symbols conflict with existing ones:

class A
{
    void foo() {}
    mixin("void foo() {}"); // error, need to add manual "namespace" wrapper
    mixin func!"foo" Sub; // does this out of the box
}

It also slightly improves error messages because semantic analysis of generated code is done in template declaration context as opposed to whole aggregate.

In general it is pretty good styling rule to follow by default even if it does not make any real difference in simple cases like this one.