November 10, 2009
Lars T. Kyllingstad wrote:
> Jacob Carlborg wrote:
>> On 11/10/09 01:27, Bill Baxter wrote:
>>> On Mon, Nov 9, 2009 at 4:09 PM, Walter Bright
>>> <newshound1@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
>>
>> This is invaluable to me, which makes it possible to do some form of duck typing at compile time:
>>
>> static if (is(typeof({
>> /* does this compile */
>> })))
> 
> There are forces at work (Don, that is) attempting to get rid of that very construct and replace it with something better:
> 
> http://www.digitalmars.com/d/archives/digitalmars/D/Proposal_Replace_traits_and_is_typeof_XXX_with_a_magic_namespace_._99914.html 
> 
> 
> In my humble opinion, is(typeof({...})) is an ugly creature. I really don't think it should be put under a spotlight as a good example of D metaprogramming. If anything, please use __traits(compiles, {...}) instead.

Who cares about "ugly" syntax, if the idea is bad in the first place?

> -Lars
November 11, 2009
grauzone wrote:
> Lars T. Kyllingstad wrote:
>> Jacob Carlborg wrote:
>>> On 11/10/09 01:27, Bill Baxter wrote:
>>>> On Mon, Nov 9, 2009 at 4:09 PM, Walter Bright
>>>> <newshound1@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
>>>
>>> This is invaluable to me, which makes it possible to do some form of duck typing at compile time:
>>>
>>> static if (is(typeof({
>>> /* does this compile */
>>> })))
>>
>> There are forces at work (Don, that is) attempting to get rid of that very construct and replace it with something better:
>>
>> http://www.digitalmars.com/d/archives/digitalmars/D/Proposal_Replace_traits_and_is_typeof_XXX_with_a_magic_namespace_._99914.html 
>>
>>
>> In my humble opinion, is(typeof({...})) is an ugly creature. I really don't think it should be put under a spotlight as a good example of D metaprogramming. If anything, please use __traits(compiles, {...}) instead.
> 
> Who cares about "ugly" syntax, if the idea is bad in the first place?

I think testing types during compilation isn't bad. Under what circumstances is it?

Andrei
November 11, 2009
Andrei Alexandrescu wrote:
> grauzone wrote:
>> Lars T. Kyllingstad wrote:
>>> Jacob Carlborg wrote:
>>>> On 11/10/09 01:27, Bill Baxter wrote:
>>>>> On Mon, Nov 9, 2009 at 4:09 PM, Walter Bright
>>>>> <newshound1@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
>>>>
>>>> This is invaluable to me, which makes it possible to do some form of duck typing at compile time:
>>>>
>>>> static if (is(typeof({
>>>> /* does this compile */
>>>> })))
>>>
>>> There are forces at work (Don, that is) attempting to get rid of that very construct and replace it with something better:
>>>
>>> http://www.digitalmars.com/d/archives/digitalmars/D/Proposal_Replace_traits_and_is_typeof_XXX_with_a_magic_namespace_._99914.html 
>>>
>>>
>>> In my humble opinion, is(typeof({...})) is an ugly creature. I really don't think it should be put under a spotlight as a good example of D metaprogramming. If anything, please use __traits(compiles, {...}) instead.
>>
>> Who cares about "ugly" syntax, if the idea is bad in the first place?
> 
> I think testing types during compilation isn't bad. Under what circumstances is it?

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. At least when you're doing more complex stuff with is(typeof), the danger of silent failures increases. Suppose the user makes an error in his custom range type by specifying a wrong return type (or whatever), and the range library just ignores his range-related function. Maybe that range function was optional, which will end in the range library seemingly ignoring his function. Can this be good? (I don't know if that case I described can even happen in your ranges lib, but I think this is a typical failure that could happen with is(typeof).)

This isn't even compiletime duck typing anymore, it's try-and-error built into the compiler. Even worse, now having semantically incorrect code in D sources is perfectly fine for weird reasons, and the compiler has to "swallow" some kinds of semantics errors.

Really, wouldn't some mechanism to explicitly check for compile time contracts better?

For me, this is some sort of metaprogramming WTF. This all makes me cringe. Sorry about that.

> Andrei
November 11, 2009
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.

So it requires caution, and you want to keep the contents small. It's useful, but it requires caution.
November 11, 2009
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.

> So it requires caution, and you want to keep the contents small. It's useful, but it requires caution.

I don't even think it particularly requires caution. If it passes, you know everything is OK. It's just that it's an all-or-nothing test.

IMHO, one of the best features of it, is that you can have negative compile-time unit tests. You can create tests which must be rejected at compile time. I don't know of any other clean way to do that.
November 11, 2009
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

>> So it requires caution, and you want to keep the contents small. It's useful, but it requires caution.
> 
> I don't even think it particularly requires caution. If it passes, you know everything is OK. It's just that it's an all-or-nothing test.

And if it doesn't pass, you know something is not ok? Then shouldn't you raise an error? Oh wait...

> IMHO, one of the best features of it, is that you can have negative compile-time unit tests. You can create tests which must be rejected at compile time. I don't know of any other clean way to do that.

True; that's another use of this feature.
November 11, 2009
grauzone 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

Then different isXxxRange are used by higher-order ranges in defining refined interfaces depending on the interfaces offered by their inputs. I fail to see how that's terrible. I am very happy D has that feature - no other statically-typed language has it, and it can be used to great effect. Look e.g. at Chain:

http://dsource.org/projects/phobos/browser/trunk/phobos/std/range.d#L799

There, the uses of static if (is(...)) allow Chain to define as capable an interface as its inputs allow.


Andrei
November 11, 2009
Andrei Alexandrescu wrote:
> grauzone 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
> 
> Then different isXxxRange are used by higher-order ranges in defining refined interfaces depending on the interfaces offered by their inputs. 

That means if one isXxxRange fails because the user maybe made a typo in the needed range function, the code will silently do something else.

But my main problem is that the user just gets a "does not match template declaration" compiler error when he messes up his range interface. He's neither told that e.g. his range-related function returns the wrong type, nor is there any other refined error message.

Now what if we'd introduce some sort of interfaces for type checking at compile time?

interface InputRange(T) {
	void popFront();
	bool empty();
	T front();
}

struct MyRange : InputRange!(int) {
	void popFront() { ... }

	//compiler error goes here...
	void empty() { ... }

	int front() { ... }
}

(or something like this)

PS: there are two aspects to the problem: 1. even compile time duck typing shares some of the problems of runtime duck typing, and 2. utterly unhelpful error messages. If you wouldn't explicitly check the interface with is(typeof()), the compiler's error messages would be even worse because of 1.

> I fail to see how that's terrible. I am very happy D has that feature - no other statically-typed language has it, and it can be used to great effect. Look e.g. at Chain:
> 
> http://dsource.org/projects/phobos/browser/trunk/phobos/std/range.d#L799
> 
> There, the uses of static if (is(...)) allow Chain to define as capable an interface as its inputs allow.
> 
> 
> Andrei
November 11, 2009
On Wed, 11 Nov 2009 10:30:24 -0600, Andrei Alexandrescu <SeeWebsiteForEmail@erdani.org> wrote:

>
>Then different isXxxRange are used by higher-order ranges in defining refined interfaces depending on the interfaces offered by their inputs. I fail to see how that's terrible.

It is not terrible. It just doesn't give any clue about what exactly is wrong with the entity for which interface validation has failed. I tend to put the code that defines the interface in a separate template to be able to find out the exact error.

And because neither _traits(compiles) nor is(typeof) can be currently
used to test template instantiations, the code goes to a mixed-in
string and the whole affair gets messy. This is the result:

private enum inputRangeConcept = q{{

        R r;             // can define a range object
        if (r.empty) {}  // can test for empty
        r.popFront;          // can invoke next
        auto h = r.front; // can get the front of the range
     }};

template InputRangeConcept(R)
{
   mixin ("void _()" ~ inputRangeConcept);
}

template isInputRange(R)
{
  enum isInputRange = is(typeof(mixin(inputRangeConcept)));
}

So, for example:

alias InputRangeConcept!(int) check;

will yield

test.d(20): Error: no property 'empty' for type 'int'
test.d(21): Error: no property 'popFront' for type 'int'
test.d(22): Error: no property 'front' for type 'int'

which gives exact information about what is wrong with int candidate for input range position (line numbers are incorrect, though).






November 12, 2009
On Mon, Nov 9, 2009 at 6:03 PM, Andrei Alexandrescu <SeeWebsiteForEmail@erdani.org> wrote:
> Bill Baxter wrote:
>>
>> On Mon, Nov 9, 2009 at 4:09 PM, Walter Bright <newshound1@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
>
> std.random has code that checks the parameters of a congruential RNG during compilation. That's also an example in TDPL.

This looks good.
Any chance you could send me the snippet of the book that explains the
rationale for what constitutes "proper linear congruential
parameters"?

--bb