Making Metaprogramming Pleasant and Fun
Chad J
chadjoan at __spam.is.bad__gmail.com
Sun Aug 23 21:25:19 PDT 2009
So I'm seeing this recurring pattern on the newsgroup:
Person 1: "Hey we should implement feature X! It'll be awesome!"
Person 2: "Bah, you can implement that in current D code with mixins:"
< insert example of typical mixin usage in D >
mixin(Foo!(args,
`//blah blah
`));
OR
mixin Foo!(args,
`//blah blah
`);
Person 3: "That's hideous! Let's not do it."
(silence or <insert discussion of mixins and ugliness>)
(maybe insert mention of CTFE gobbling up all of your memory and kittens)
As much as I hate to do it, I'm going to be /that/ guy and make another
feature suggestion. Or 2 or 3.
----------------------------
Suggestion 1:
For any template whose argument list ends with a string argument, such
as this one:
template foo( T, string arg )
{
...
}
... allow it to be instantiated (or mixed in) like so:
foo!(T)
{
// Some token string.
}
or
mixin foo!(T)
{
// Some token string.
}
The contents of the curly braces are treated as a token string, like the
q{ foo + bar } variety, minus the unbalancing q.
This gets us to things like
mixin property!(int,"foo")
{
get { return $; }
set { $ = value; }
}
Bonus points: generalize it to IFTI functions.
void foo(T, string code)( T arg )
can be called like so:
foo(arg)
{
// code goes here.
}
Then use your imagination.
----------------------------
Let templates include expression statements. Optionally make it invalid
to NOT use these as mixin templates. This would allow us to convert
things in general from
mixin(Foo!(args)
{
//blah blah
});
to
mixin Foo!(args)
{
//blah blah
}
Those aforementioned bonus points become much more valuable with this.
void main()
{
// etc
mixin foreachReverse!( "ref elem", someRange )
{
elem = someFunc(elem);
// and so on.
}
}
Admittedly I haven't pondered the negative consequences of this
particular change too much.
----------------------------
Bikeshedding: make a mixin operator to complement the keyword.
Thus
mixin Foo!(args) { ... }
becomes
Foo@(args) { ... }
Now then...
class SomeElementType
{
...
property@(int,"foo")
{
get { ... }
set { ... }
}
}
void main()
{
// etc
foreachReverse@( "ref elem", someRange )
{
elem.foo = someFunc(elem);
// and so on.
}
}
Smooth.
----------------------------
Also, the CTFE memory leak. But I'm sure everyone who needs to know
about that already knows and is sick of hearing about it.
----------------------------
That's all I got for now.
More information about the Digitalmars-d
mailing list