Ducks

Chris Williams yoreanon-chrisw at yahoo.co.jp
Wed Feb 5 17:01:57 PST 2014


I found some old threads about the concept of "static interface":

http://forum.dlang.org/thread/20091116172513.GB13817@llucax.com.ar

I agree that using template checks to validate compilability is 
more flexible than interface definitions, specifically because 
you can create cross-compatibility between functions and 
properties or allow for undefined types. However, I think that 
template checks have two large flaws:

1. You only know what the target is that you have to hit by 
looking at their source. Or, the person who wrote the template 
checker needs to, effectively, rewrite their check as a document 
comment. (E.g. see std.range isInputRange)

2. Writing functions which are restricted to a particular type is 
long-winded and subsequently error-prone. (E.g. all 
implementations of std.random uniform() should check 
isUniformRNG(), when they accept an external generator)

I think that the advantages that are added by template-based 
compilability checks can be gained without losing flexibility if 
we add a more lenient interface definition, like:

duck InputRange {
   bool empty; // can be a function or not. Doesn't care. Anyone 
using it must avoid using () syntax
   auto front; // Doesn't care what the return type is so long as 
it's non-void
   void next; // Cannot return a value
}

While a "duck" would allow one to define methods with explicitly 
typed parameters and return types like:

duck IntStack {
    void push(int value); // must accept an int
    int pop(); // must be a method that returns an int
}

It's easy and preferred to define ducks with the greatest 
flexibility.

Since these would still be a feature of the templating system, I 
might recommend using them like:

void foo(Range : InputRange)(Range r) {
    ...
}

Rather than:

void foo(InputRange r) {
    ...
}

It's still a little bit verbose, but it would help people to 
notice that ducked parameters are available at compile-time only.

And since these would be an official part of the language, DDoc 
would generate a public definition of the type target, like it 
does with interfaces.

I would also suggest a further version of ducks, for things like 
this:

duck Integral if (is(Integral : int)); // not a particularly good 
check

Thus allowing code like:

void foo(Int : Integral)(Int i) {
    ...
}

These wouldn't be quite as self-documenting, but I think would 
allow the general collapse of type specialization into the type 
specialization field.


More information about the Digitalmars-d mailing list