of "Conditional Implementation" vs "Assertive Input Validation"

xenon325 1 at mail.net
Tue Jul 24 22:30:59 PDT 2012


On Tuesday, 24 July 2012 at 12:50:08 UTC, Jacob Carlborg wrote:

> That will be just a little better. The problem is it will leak 
> implementation details. For this to be useful you really need 
> to create a template for every condition:
>
> template isFoo (T)
> {
>     enum isFoo = is(T == Foo);
> }
>
> void foo (T) (T t) if (isFoo!(T));
>
> If you just do it like this:
>
> void foo (T) (T t) if (is(T == Foo));
>
> Then it will leak the "raw" condition.

hmm, yeah that could be hard for novices


> With my approach the constraint will have a name which should 
> result in a lot better error messages.

How is it different from creating a template for every condition 
? ;)

Honestly, I don't quite get what's the difference between current 
template constraints and ones you're proposing:

// yours
constraint InputRange (Range)
{
     alias ElementType!(Range.init) E;

     @property bool empty ();
     void popFront ();
     @property E front ();
}

// std.range
// 
https://github.com/D-Programming-Language/phobos/blob/master/std/range.d#L549
template isInputRange(R)
{
     enum bool isInputRange = is(typeof(
     (inout int _dummy=0)
     {
         R r = void;       /*** how would you express this b.t.w. 
? ***/
         if (r.empty) {}
         r.popFront();
         auto h = r.front;
     }));
}

on the call site it's as convenient and clear as yours.
On the definition site, yes, syntax maybe is a tad worse,
but it's not *that* bad to require introduction of a new
language construct.

Actually the only thing constraint writer needs to know is that
     `is(typeof(<code>))`
means "compiles". All the rest is perfectly clear.


> Think of it like this. You have a function, "foo", taking an 
> interface parameter, "Foo":
>
> interface Foo
> {
>     void a ();
>     void b ();
>     void c ();
> }
>
> void foo (Foo f);
>
> You then call the function with an object that does _not_ 
> implement the function, then you get a proper easily 
> understandable error message:
>
> foo(new Object);
>
> Error: Object doesn't implement Foo
>
> What would you think if the error message look like this 
> instead:
>
> Error: Object doesn't have the methods:
>     void a ();
>     void b ();
>     void c ();
>
> Now imagine that with a bunch of conditions instead.
>
> void foo (T) (T t) if (__traits(compiles, { T t; t.foo; t.bar; 
> }) || is(T : Foo));
>
> Error: template foo does not match any function template, 
> constraints values are:
>      __traits(compiles, { T t; t.foo; t.bar }) false
>      is(T : Foo) false

I think I've addressed these points, let me know if
I can explain it better.



More information about the Digitalmars-d mailing list