www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - mixin templates with name parameter

reply "js.mdnq" <js_adddot+mdng gmail.com> writes:
mixin templates seems like they could benefit from an extra 
parameter that one can pass a name. The name, a string literal, 
sort of acts like a preprocessor token:

mixin template InjectX!(T)
{
     private T x;
     T get#name#( ) { return x; }
     void set#name#(T y)
     {
        // Checks
        x = y;
     }
}

Then something like "mixin InjectX!int Mylnt;" will create the 
following function

getMylnt and setMylnt.

The scope names are a nice solution and sometimes what one wants. 
But sometimes one would like to avoid an extra referencing step.

In fact, it would be nice if one could inject code into the 
template code. One, could example, even supply an object or 
another mixin with the mixin to compose the code. If, say, I 
wanted slightly different set functions above I would have to 
write a template for each one, but if I code compose mixins then 
I could avoid that.

In any case, it can get rather complicated and notation is the 
key issue(how to describe it all elegantly). I think the idea and 
the way D does it is pretty elegant though and probably good 
enough for most cases. I just imagine cases where a very complex 
mixin might need slight changes from one use to the next but 
unfortunately would require some inelegant methods to use it.

Possibly one could compose mixins in a way that all common 
function overlap are serialized.

"alias mixin InjectX!int with InjectY!int Mylntalias;"
"mixin MyIntalias!int MyInt;"

will produce a mixin s.t., the set functions of Y are serialized 
with those of X. (the new set function will first call the set of 
InjectY then that of InjectX)

This way, we can "extend" a mixin relatively easy by simply 
"appending" code to it's functions.


Just some food for thought.
Nov 29 2012
next sibling parent =?UTF-8?B?QWxpIMOHZWhyZWxp?= <acehreli yahoo.com> writes:
On 11/29/2012 05:08 PM, js.mdnq wrote:
 mixin templates seems like they could benefit from an extra parameter
 that one can pass a name. The name, a string literal, sort of acts like
 a preprocessor token:

 mixin template InjectX!(T)
 {
 private T x;
 T get#name#( ) { return x; }
 void set#name#(T y)
 {
 // Checks
 x = y;
 }
 }

 Then something like "mixin InjectX!int Mylnt;" will create the following
 function

 getMylnt and setMylnt.

 The scope names are a nice solution and sometimes what one wants. But
 sometimes one would like to avoid an extra referencing step.

 In fact, it would be nice if one could inject code into the template
 code. One, could example, even supply an object or another mixin with
 the mixin to compose the code. If, say, I wanted slightly different set
 functions above I would have to write a template for each one, but if I
 code compose mixins then I could avoid that.

 In any case, it can get rather complicated and notation is the key
 issue(how to describe it all elegantly). I think the idea and the way D
 does it is pretty elegant though and probably good enough for most
 cases. I just imagine cases where a very complex mixin might need slight
 changes from one use to the next but unfortunately would require some
 inelegant methods to use it.

 Possibly one could compose mixins in a way that all common function
 overlap are serialized.

 "alias mixin InjectX!int with InjectY!int Mylntalias;"
 "mixin MyIntalias!int MyInt;"

 will produce a mixin s.t., the set functions of Y are serialized with
 those of X. (the new set function will first call the set of InjectY
 then that of InjectX)

 This way, we can "extend" a mixin relatively easy by simply "appending"
 code to it's functions.


 Just some food for thought.

There are also string mixins, which provide some help: string getFunction(string name)() { return "T get" ~ name ~ "( ) { return x; }"; } string setFunction(string name)() { return "void set" ~ name ~ "(T y)" ~ q{ { // Checks x = y; } }; } string varDeclaration(string name)() { return "private T " ~ name ~ ";"; } template InjectX(T, string name) { mixin (varDeclaration!name); mixin (getFunction!name); mixin (setFunction!name); } class C { mixin InjectX!(int, "x"); } void main() { auto c = new C; c.getx(); c.setx(42); } There is a warning though: The current compiler is very slow when there are too many little string mixins. I heard that one large function that generates all three string above would be way faster than the three that I have used. Ali
Nov 29 2012
prev sibling parent "js.mdnq" <js_adddot+mdng gmail.com> writes:
On Friday, 30 November 2012 at 04:04:10 UTC, Ali Çehreli wrote:
 On 11/29/2012 05:08 PM, js.mdnq wrote:
 mixin templates seems like they could benefit from an extra 
 parameter
 that one can pass a name. The name, a string literal, sort of 
 acts like
 a preprocessor token:

 mixin template InjectX!(T)
 {
 private T x;
 T get#name#( ) { return x; }
 void set#name#(T y)
 {
 // Checks
 x = y;
 }
 }

 Then something like "mixin InjectX!int Mylnt;" will create the 
 following
 function

 getMylnt and setMylnt.

 The scope names are a nice solution and sometimes what one 
 wants. But
 sometimes one would like to avoid an extra referencing step.

 In fact, it would be nice if one could inject code into the 
 template
 code. One, could example, even supply an object or another 
 mixin with
 the mixin to compose the code. If, say, I wanted slightly 
 different set
 functions above I would have to write a template for each one, 
 but if I
 code compose mixins then I could avoid that.

 In any case, it can get rather complicated and notation is the 
 key
 issue(how to describe it all elegantly). I think the idea and 
 the way D
 does it is pretty elegant though and probably good enough for 
 most
 cases. I just imagine cases where a very complex mixin might 
 need slight
 changes from one use to the next but unfortunately would 
 require some
 inelegant methods to use it.

 Possibly one could compose mixins in a way that all common 
 function
 overlap are serialized.

 "alias mixin InjectX!int with InjectY!int Mylntalias;"
 "mixin MyIntalias!int MyInt;"

 will produce a mixin s.t., the set functions of Y are 
 serialized with
 those of X. (the new set function will first call the set of 
 InjectY
 then that of InjectX)

 This way, we can "extend" a mixin relatively easy by simply 
 "appending"
 code to it's functions.


 Just some food for thought.

There are also string mixins, which provide some help: string getFunction(string name)() { return "T get" ~ name ~ "( ) { return x; }"; } string setFunction(string name)() { return "void set" ~ name ~ "(T y)" ~ q{ { // Checks x = y; } }; } string varDeclaration(string name)() { return "private T " ~ name ~ ";"; } template InjectX(T, string name) { mixin (varDeclaration!name); mixin (getFunction!name); mixin (setFunction!name); } class C { mixin InjectX!(int, "x"); } void main() { auto c = new C; c.getx(); c.setx(42); } There is a warning though: The current compiler is very slow when there are too many little string mixins. I heard that one large function that generates all three string above would be way faster than the three that I have used. Ali

Yeah, it's a bit "stringy" for my tastes but it does provide a solution. I suppose one can actually store the templates in another file and parse them beforehand(sort of preprocessing) and just replace all occurrences of #name# with the name provided? e.g., templates = import("templates.dtp") mixin parsename(templates, "myname"); (just pseudo code, I don't know enough about D yet to get it to work) templates.dtp would be normal template mixins(not stringified) except using #name# as a name token. parsename will simply replace #name#(or whatever symbol used) with the 2nd parameter. mixin will mix it in as normal.
Nov 30 2012