Metaprogramming in D : Some Real-world Examples

Bill Baxter wbaxter at gmail.com
Thu Nov 12 05:01:20 PST 2009


On Wed, Nov 11, 2009 at 8:23 AM, grauzone <none at example.net> wrote:
> Don wrote:
>>
>> Christopher Wright wrote:
>>>
>>> grauzone wrote:
>>>>
>>>> You're not testing for types, you're testing if it compiles. Inside the
>>>> tested block of code, all sorts of things could go wrong. You can't know if
>>>> is(typeof(...)) really did what you wanted, or if something broke.
>>
>> You're testing, "is everything inside that OK?". If you want to know WHY
>> it's wrong, you'd better make sure you're testing something simple.
>
> Andrei's range lib uses it more in a way "does this type support this and
> that range interface?". Example:
> http://dsource.org/projects/phobos/browser/trunk/phobos/std/range.d#L58

But notice he also has unit tests for it that check some things which
are supposed to pass and not pass.
So if the is(typeof()) were failing because of a typo, he'd know it.
I think the problem with an interface-like specification is that things like
   if (r.empty) {}
are hard to specify other than by asking if the code compiles.  The
algo doesn't actually require an r.empty that returns bool.  It
requires an r.empty that can can be used in a conditional.  It's
actually ok if r.empty returns null on empty and non-null otherwise.
"Does this code compile" is actually the right question to ask, IMHO.

But I know what you mean.  I just don't know if it's possible to do
better.  Actually it already errors out if you give it structurally
invalid code.   For instance all these generate errors:
    static if(is(typeof{ int x   if (x) {} }))
    static if(is(typeof{ int x; iff (x) {} }))
    static if(is(typeof{ int x; if (x)) {} }))
    static if(is(typeof{ int x; for (;) {} }))

So I think the only things that give you errors are ones where you've
typed an identifier wrong, or asked for function call when you meant
indexing etc.   Given that, I'm not sure how creating interfaces would
make anything different.  You could still have typos in your interface
declaration.  I think it ends up being pretty much equivalent to
defining a "template supportsInterface(T)".   Having a "myType :
implements static Interface" syntax is the moral equivalent of "static
assert(supportsInterface!(myType))".
The only difference is that a static interface syntax might be able to
give you better error messages than "assertion failed".

Ok, so I guess that's something that would be valuable:   We need some
way to get the reason for failure from static if (is(typeof(...)).

If you had that, then I think you could write a checkInterface!(T)
that reports decent error messages.
I think I'll start another thread about that.  d.announce clearly
isn't the right place for this discussion.

----------
Somewhat related -- this topic ties into something I brought up
before.  I often find I end up writing bits of code twice:
     static if (is(typeof({ a[x] += c; }))) {
            a[x] += c;
     }
     else {
             // fallback
     }

It feels like there should be a construct that compiles some code if
it can, otherwise do something else.
Maybe:

static if {
    a[x] += c;
} else {
    // fallback
}


--bb


More information about the Digitalmars-d-announce mailing list