The many definition of duck typing (was Re: Ducktator - A Duck Type Validator)

If you were just moving there error check earlier, by using respond_to?, I
think this would be fine. The problem I have with what you did is that you
are also checking "class". The only example I saw checked that the argument
was a Hash. On top of that you state that you want some type of static type
checking in the language. That is clearly not duck typing.

Describing the "duck type" of something can be quite difficult. In addition
to describing what it responds to, you'll need to recursively describe the
"duck type" of the arguments and return value of those methods. And then
if the thing is stored in an instance variable (or class or global) you'll
need to know how it will eventually get used.

If you wanted checking ahead of time, I think the best thing would be to
analyze the code and figure all of the out. You might even find errors at
this point, but ruby's dynamic nature may make this difficult.

I think an unfortunate thing about the term "duck typing" is that it has
multiple meanings. If you look in the pickaxe book, the "Duck Typing"
chapter presents several concepts which people can claim to be "duck
typing":

1. don't worry about the type of an object. Just use its methods and assume
whoever made the object has those capabilities. You'll get a method missing
error if it doesn't have those methods. This is the primary definition I
use. I think a "duck type" in this context is analogous what C++ STL calls
a "concept" - which is only described in documentation (for now at least).

2. use respond_to? ahead of time to check the object instead of waiting for
a method missing error. This is discouraged though as it creates code
bloat.

3. "the type of an object is defined by what that object can do. In Ruby,
we call this duck typing. If an object walks like a duck and talks like a
duck, then the interpreter is happy to treat it as if it were a duck." In
the context of the examples surrounding this, I think this means the same as
#1. But, if you take this out of context, the exact wording of this looks
to mean the "type" of an object is defined by its entire set of
capabilities. So, 2 objects have the same "type" only if they have the same
capabilities/methods. So, you have to mimic an entire class to have the
same "type" by this definition. So, you might say that StringIO has the
same type as IO - but even this falls short as there are a few differences
in capabilities. I'm not where this concept of "type" in ruby is useful.

4. multimethods based on an object's capabilities. The example given is for
File.new where it can either take something responding to #to_int (taking
the result as a file descriptor) or something to #to_str (taking it as a
filename). I think it is better to simply define different methods. With
the multimethod approach you have to be careful which methods you use to
choose with, as some objects you want to use may have methods for multiple
cases. For example, you define a method called "go" that will either cause
its argument to "fly", "walk", or "swim" depending on which of those methods
it responds to. What if you give this method a duck which happens to do all
3? Ambiguity.

5. using conversion methods: #to_*. At first, this looks like just a
special case of #1 - you can use these take any argument that responds to
some #to_* method. You need to look one level deeper though - at what is
returned by this method. For most cases, it ends up just being static
typing with a convenient conversion layer to that static type (exact
class). For example, the #to_str method has to typically return a String,
not an object that responds to some subset of methods of String.

No wonder people have so many concepts for "duck typing". I think it was a
mistake to make the title of this chapter "Duck Typing". It should have
been more generic. I've seen people on ruby-talk use each of these concepts
to mean "duck typing" - plus others.

ยทยทยท

On 9/20/06, Ola Bini <ola.bini@ki.se> wrote:

Robert Klemme wrote:
> On 20.09.2006 10:58, MonkeeSage wrote:
>> Robert Klemme wrote:
>>> I do not think that the use of respond_to? is a regular duck typing
>>> technique. As Eric put it, respond_to? is exactly not applied
regularly
>>> when duck typing.
>>>
>>> Don't get me wrong, I don't say your lib is useless (in fact I
envision
>>> numerous uses for test cases etc.) but I think this claim of yours is
>>> wrong.
>>
>> Not to push the issue, but Wikipedia seems to think that this is a
>> valid claim [1]:
>>
>> "[...A]n object having all the methods described in an interface can be
>> made to implement that interface dynamically at runtime, even if the
>> object's class does not include the interface in its implements
>> clause. It also implies that an object is interchangeable with any
>> other object that implements the same interface, regardless of whether
>> the objects have a related inheritance hierarchy."
>>
>> respond_to? in ruby is just a dynamic way of checking that "an object
>> is interchangeable with any other object that implements the same
>> interface".
>
> The article does not claim that a client needs to check this. And in
> Ruby you generally do not do that either, you just use it. It just
> states that it's possible for an object to /dynamically/ implement a
> certain interface although it is not declared.

The problem with "just use it", is that you will have no control over
error handling in this case. In most situations, the error is the
programmers, in which case it doesn't matter, but when reading in
something you're not entirely sure what it is, it's better to be able to
report consistently what's wrong to the user instead of failing randomly
with a method_missing in the middle of nowhere.