digitalmars.D - Ducks
- Chris Williams (58/58) Feb 05 2014 I found some old threads about the concept of "static interface":
- Francesco Cattoglio (14/17) Feb 06 2014 I love the idea of some kind of "static interface" too. Pretty
- Jakob Ovrum (27/45) Feb 06 2014 The documentation must explain everything the concept entails. It
- Chris Williams (8/10) Feb 06 2014 Making them interchangeable with Interfaces is certainly an
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.
Feb 05 2014
On Thursday, 6 February 2014 at 01:01:59 UTC, Chris Williams wrote: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:I love the idea of some kind of "static interface" too. Pretty sure it would also allow better compile-time polymorphism. The problem I see with this proposal however is that the chances of getting it into the core language are zero. Perhaps one could get a library solution if what we are looking for is extra clarity. Something like void DoSomething(T)(T t) if (DuckTyping(T, MyType) { ... stuff ... }
Feb 06 2014
On Thursday, 6 February 2014 at 01:01:59 UTC, Chris Williams wrote: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)The documentation must explain everything the concept entails. It is not acceptable that the user is forced to look at Phobos' source code to figure out a public interface. If that's forced anywhere in Phobos, it's a bug. While it's not hard to remember that an input range needs a boolean property `empty`, a property `front` of any non-void type and a void `popFront()` method, I agree that a more formalized solution of documenting concepts would be an improvement. The current method of replicating a documented version of the source code in the documentation is a bit icky, as the user has to *derive* how to write their types based on that code snippet.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)Perhaps error prone, but in terms of conciseness there aren't that many differences: --- // Concepts (current approach) T uniform(T, RNG)(ref RNG rng) if (isUniformable!T && isUniformRNG!RNG); // Interfaces T uniform(T)(IUniformRNG rng) if (isUniformable!T); // Protocols T uniform(T : IUniformable, RNG : IUniformRNG)(ref RNG rng); --- It seems only the interface approach can claim being less error prone.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 }It is usually called a "protocol".
Feb 06 2014
On Thursday, 6 February 2014 at 10:31:45 UTC, Jakob Ovrum wrote:It seems only the interface approach can claim being less error prone.Making them interchangeable with Interfaces is certainly an option. It's easy to write and doesn't actually lose anything in the end result. I was figuring that proximity to the target would make people less likely to forget to specialize their templates and for people looking at the definition to figure out what limitations were being attached to what, but I'm an easy sell for short-to-type and easy-to-read.
Feb 06 2014