David Naseby
11/6/2003 6:33:00 AM
<snip lots>
> ARRAY_DUCK = [:first, :last, :[], :each]
>
> def foo(a, b)
> expect_duck a, ARRAY_DUCK, b, ARRAY_DUCK
> :
> end
>
>Now, you probably see where I'm going with this. Where I've already
>gone, actually. This is a simple reinvention of classes, just lacking
>important semantic information.
>
>You can also treat a class (or module) itself as the behavioral
>specification, and with it you gain the important semantic
>differentiation between the proverbial ducks and platypuses.
>You can simply ask, "is this a Foo?", and know that it will act like
>you want. When you make a thing that acts like a Foo, you can
>subclass or include Foo, to show what you mean.
Asking if its a Foo sets in stone the use of your code, as you say. It
disambiguates, and documents at the same time, again, as you said.
But to stretch every analogy to breaking, seeing as you brought them up,
imagine its the 17th century and you write your code to expect a Duck. The
conditions of swimming and having a bill could apply to nothing else.. err..
except some other waterfowl! OK.. so you generalise back and create a
Waterfowl class, and you are all documented and happy that your code uses
Waterfowl, and nothing but Waterfowl.
Then the 18th century rolls around, and the platypus emerges. Its certainly
not a Waterfowl, but it does have a bill and swims, and it would benefit
from your code. But it is blocked from using it. Your strong typing reduced
your codes benefit to a use you could not have *possibly* have predicted.
Dynamic duck typing allows for serendipity at the cost of some
self-documentation.
David.