Metaprogramming in D : Some Real-world Examples

Denis Koroskin 2korden at gmail.com
Thu Nov 12 05:21:09 PST 2009


On Thu, 12 Nov 2009 16:01:20 +0300, Bill Baxter <wbaxter at gmail.com> wrote:

> 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

string expression = "a[x] += c";
static if (meta.compiles(expression)) {
     mixin(expression);
} else {
     // fallback
}

or even like this:

expr expression = "a[x] += c";
static if (expression.compiles) {
     expression(); // or expression.evaluate();
} else {
     // fallback
}


More information about the Digitalmars-d-announce mailing list