On Sep 28, 2010, at 12:35 PM, Loren Segal wrote:

> We've all seen and written these methods before. They're annoying to write, they're even harder to document. Why couldn't we just do (forgive me, I'm using a different syntax to that which was proposed in this thread):
> 
>    def run(opts: Hash)
>      Server.new(opts).start
>    end
> 
>    def run(server: Server)
>      server.start
>    end
> 
> Before all the duck-typists go nuts, there's no reason why you couldn't specify a duck-type here.

The problem is that this proposal fundamentally misunderstand the concept of Duck typing. What if I create a class which behaves exactly as a Hash, has all the same methods with the same signatures as a Hash, but I call my class FunTimeCrazyDuckyHash? Which of these methods should be called?

If you're testing your arguments against a specific class, you're "Doing it wrong". And all of us have done this at some point, but that still makes it wrong. The "duck type" way to write the above is:

def run(thing)
  if thing.respond_to? :start
    thing.start
  else
    Server.new(thing).start
  end
end

Mostly, if you find yourself doing this sort of checking too often, it's probably symptomatic of a larger issue with the structure of your code.

In other words: "duck-type" means "behavior determines type". If you're not testing for behavior, you're not using duck-typing.

Cheers,