Metaprogramming in D : Some Real-world Examples

Bill Baxter wbaxter at gmail.com
Thu Nov 12 04:21:22 PST 2009


On Tue, Nov 10, 2009 at 3:32 AM, Lutger <lutger.blijdestijn at gmail.com> wrote:
> Bill Baxter wrote:
>
>> On Mon, Nov 9, 2009 at 4:09 PM, Walter Bright
>> <newshound1 at digitalmars.com> wrote:
>>> Looks like Bill Baxter is giving a presentation on D Nov. 18!
>>>
>>> http://www.nwcpp.org/
>>
>> Yep, that's right, and I'd be quite grateful to you smart folks here
>> if you could share your meta-programming favorites with me!   If
>> you've got a real-world example of meta-programming in D that you
>> think is particularly handy, then please send it my way
>>
>> I'm looking for small-but-useful things that are easy to explain, and
>> make something easier than it would be otherwise.  Things like places
>> where static if can save your butt,  or loop unrolling,  and passing
>> code snippets to functions like in std.algorithm.
>>
>> Things like a compile-time raytracer or regexp parser (though quite
>> cool!) are not what I'm after.  Too involved for a short talk.
>>
>> --bb
>
> Great, I hope to see some slides or a video!
>
> Here is a watered down example of what I currently use to help with the
> boilerplate code of a visitor. It doesn't look much, but it's helpful when
> you have lots of visitable classes and in case of adding new classes. The
> code should run as is:
>
> import std.stdio;
>
> enum Visitable =
> q{
>    override void accept(IVisitor visitor)
>    {
>        visitor.visit(this);
>    }
> };
>
> interface IExpression
> {
>    void accept(IVisitor visitor);
> }
>
> class Sum : IExpression
> {
>    mixin(Visitable);
> }
>
> class Product : IExpression
> {
>    mixin(Visitable);
> }
>
> string visitMethodOf(string type)
> {
>    return "void visit(" ~ type ~ ");";
> }
>
> string FoldStringsOf(alias F)(string[] list)
> {
>    string result = "";
>    foreach (element ; list)
>        result ~= F(element);
>    return result;
> }
>
> interface IVisitor
> {
>    mixin( FoldStringsOf!visitMethodOf( ["Sum", "Product"] ) );
> }
>
> class Visitor : IVisitor
> {
>    void visit(Sum node)
>    {
>        writeln("sum");
>    }
>
>    void visit(Product node)
>    {
>        writeln("product");
>    }
> }
>
> void main()
> {
>    auto printer = new Visitor();
>
>    IExpression sum = new Sum();
>    IExpression product = new Product();
>
>    sum.accept(printer);
>    product.accept(printer);
> }
>

This is almost just a preprocessor macro trick, except for this line:
     mixin( FoldStringsOf!visitMethodOf( ["Sum", "Product"] ) );

The essence is to generate a bunch of methods from a list of names.  I
was thinking to include a similar example from the world of 3d
graphics, which is generating all the swizzles of a vector* (got the
idea from Tom S.).  That's got the method generation from a list, but
it also generates the list too.

Another way is to have a swizz member template that lets you do
v.swiz("zyx").  That's arguably better in that you don't pay for it if
you don't use it.  But being able to generate all the methods with D
is still kinda spiffy.

* Most GPU languages (HLSL,glsl,Cg) have a swizzle syntax, such that
for a float3 v;   v.zyx  gives you float3(v.z,v.y,v.x).  And this
works for all suffixes.   v.xxx, v.xzy, etc.  Also for different
numbers of components.   eg.  v.xz is float2(v.x,v.z).

--bb


More information about the Digitalmars-d-announce mailing list