www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - template mixins for boilerplate

reply "Paul D Anderson" <claude.rains msn.com> writes:
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
Jun 20 2014
next sibling parent Philippe Sigaud via Digitalmars-d-learn writes:
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());
}
Jun 20 2014
prev sibling parent reply Artur Skawina via Digitalmars-d-learn <digitalmars-d-learn puremagic.com> writes:
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
Jun 21 2014
parent reply "Paul D Anderson" <claude.rains msn.com> writes:
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
Jun 21 2014
parent reply Philippe Sigaud via Digitalmars-d-learn writes:
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?
Jun 21 2014
parent reply "Dicebot" <public dicebot.lv> writes:
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.
Jun 21 2014
next sibling parent reply Philippe Sigaud via Digitalmars-d-learn writes:
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")); }
Jun 21 2014
parent "Dicebot" <public dicebot.lv> writes:
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.
Jun 21 2014
prev sibling next sibling parent Artur Skawina via Digitalmars-d-learn <digitalmars-d-learn puremagic.com> writes:
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
Jun 21 2014
prev sibling parent Philippe Sigaud via Digitalmars-d-learn writes:
I see, thanks Artur.
Jun 21 2014