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.