I have done a fair bit of mixin coding using recursive templates
(inspired by std.typecons). It was an amazing taste of what you can do
in D, and I am delighted with the result - HEAPS of boiler-plate coding
vanished before my eyes. However, the template code is virtually
impossible to understand.
What you are suggesting here seems to be a way to dramatically reduce
the complexity of code that generates source-code and mixes it in. I
think something like that is needed before this mind-bogglingly powerful
feature of D can realise its potential.
There is of course the worry that it could get so easy that everyone
starts doing it, and we have (relatively) impenetrable code everywhere
instead of just deep in the bowels of framework libraries.
On 14/12/10 07:07, Jacob Carlborg wrote:
This is an idea I've been thinking of for a while, it's not a really
suggestion (at least not yet) I just wanted to here what people think
about it.
If we take a step back and look at what string mixins actually do or
rather what they're used for, that would be: inserting a piece/block
of code where the mixin expression is used. If we then take a look at
how a block of code is represented in D (how you store it in variables
and how you pass it around). It's not as a string which is used by the
mixin expression, instead delegates are used to represent a block of
code in D that can be passed around. Therefore this is my idea:
Add a new mixin operator "@" (1). When that operator is put in front
of a function call it would behave as a string mixin. The function
that is called needs to be CTFE and return a delegate or an array of
delegates:
class Foo
{
@get_set("int", "bar");
}
The above code would be the same as the following code:
class Foo
{
mixin(get_set("int", "bar"));
}
If we now move to the declaration of "get_set" this is how it could
look like:
void delegate () get_set (string type, string name)
{
return
{
@type _...@name;
@type @name ()
{
return _...@name;
}
@type @name (@type @name)
{
return _...@name = @name;
}
};
}
In the above code when "@" is used in the delegate literal it
basically behaves like string interpolation, so "@type" would be
replaced with the content of the "type" variable (2).
When the "get_set" function is called with the mixin symbol the
content of the returned delegate is inserted where the call is made.
If the function returns an array of delegates then the array would be
unfolded and the content of all the delegates would be inserted.
Taking it one step further:
Allow the mixin syntax to be placed in front of most of the
declarations and drop the need for string literals, commas and
parentheses, basically allowing the following syntax:
class Foo
{
@get_set int bar;
}
Would be translated into this:
class Foo
{
@get_set!(int)("bar");
}
Maybe one could do something like this as well:
@singleton class Foo
{
}
void delegate () singleton (string name, void delegate () classBody)
{
return { // a simple singleton implementation
class @name
{
static @name instance;
static this ()
{
instance = new @name;
}
private this () {}
@classBody;
}
};
}
Above, in the last example, @classBody would insert the content of the
delegate, basically the class body.
1. I will use "@" in this example because I think it looks good but it
would probably conflict with @nothrow, @property and others.
2. I have no idea if this usage of the mixin symbol, "@", will
conflict with the first usage.
--
Graham St Jack