On Fri, 13 Aug 2010 13:20:32 -0400, Ryan W Sims <[email protected]> wrote:

On 8/13/10 10:01 AM, simendsjo wrote:
While reading std.range, I though that a ducktyping design without
language/library support can be quite fragile.

Consider the following example:

import std.stdio;

struct S
{
void shittyNameThatProbablyGetsRefactored() { };
}

void process(T)(T s)
{
static if( __traits(hasMember, T, "shittyNameThatProbablyGetsRefactored"))
{
writeln("normal processing");
}
else
{
writeln("Start nuclear war!");
}
}


void main()
{
S s;
process(s);
}


If you rename S's method, process() does something completely different
without a compile time error. By using interfaces this is avoided as the
rename would break the interface.
Is there any idoms you can use to avoid stuff like this? Relying on
documentation doesn't seem like a good solution.

If what you want is compile-time type safety, then duck typing is probably not for you. That's sort of the whole point behind duck typing: you defer typing decisions to runtime. If you need compiler breakage for something like that, use interfaces.

No, duck typing is compile-time.  Essentially, it goes like this:

void foo(T)(T duck)
{
  duck.quack();
}

You can only call this functions on T types that can quack. If you try to call it on something else, the compiler refuses to build it.

It's very similar to interfaces, except you don't have to declare what your interface is, you just pass in an object that can compile with the function, and you are done.

Where it can get you into trouble is:

1. a function may have the same name and usage, but have a completely different meaning. Human languages are funny that way. This means, your function could accept a type as a parameter and use it in a very wrong way. Most of the time, this is a non issue, because you use duck typing with clear function names (hard to imagine another meaning for quack for instance).

2. The error might not be the function call, but in the type itself -- e.g. you spelled quack wrong. But the error does not appear as a problem with the type, just on its usage. Comparing this to interfaces, you declare to the compiler that your object implements a certain interface, and it errors when you don't.

-Steve

Reply via email to