# Duck-typing allows deeper polymorphism

**URL:** <https://rubytalk.org/t/duck-typing-allows-deeper-polymorphism/18892>\
**Category:** ruby-talk\
**Created:** [10 June 2005 11:42 UTC](https://rubytalk.org/t/duck-typing-allows-deeper-polymorphism/18892 "2005-06-10T11:42:52Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![Eric\_Mahurin1](https://avatars.discourse-cdn.com/v4/letter/e/34f0e0/32.png) [@Eric\_Mahurin1](https://rubytalk.org/u/Eric_Mahurin1)\
**Post date:** [10 June 2005 11:42 UTC](https://rubytalk.org/t/duck-typing-allows-deeper-polymorphism/18892/1 "2005-06-10T11:42:52Z")

</div>

I've seen many posts on what duck-typing is, that Ruby doesn't  
need static typing, that duck-typing results in easy to read  
code, etc (and others that want static typing). What I haven't  
seen much of is what advantage duck-typing gives to a method  
over conventional polymorphism. This is a follow on of my  
previous thread "making a duck". I would like to get on my  
soapbox and talk about it a little...

With the polymorphism of other languages, class hierarchy is  
very important. When you specify an argument can take a  
certain class, you are saying that it can also take anything  
derived from it (or implementing the same interface if the  
language has that concept).

With duck-typing, class hierarchy and class names are not  
important. Every argument that is duck-typed (built-in methods  
unfortunately usually aren't) effectively has its own "type".  
The "type" of an argument is defined by what methods it needs  
to respond to and any "type" requirements of those methods  
arguments or return values. If an argument has no method  
requirements, then that argument could be anything. With an  
argument needs to respond to just one method, you can think  
about making an object on-the-fly that meets that one  
requirement. That one method could easily be made from a  
method of another object - including Proc#call (arbitrary  
code). With an argument that needs to respond to more methods,  
you can still do the same (mapping multiple methods), but at a  
certain point it may become too cumbersome.

As an example, suppose you have 2 methods in an object that  
take String-like things. With conventional polymorphism, you  
might abstract this up to anything indexable to encompass  
String and Array. With duck typing, you don't need to do  
anything explicit - just continue thinking of it like a String  
when coding the methods. Let's say one of the methods reads  
from its "String" argument using only the [] method. You could  
easily use a String, Array, Hash, or more powerfully a Proc.  
The second appends to its "String" argument using the \<\<  
method. Here you could easily use a String or Array. In both  
of these cases, you could grab any method of any object and map  
it to new object (and name the method appropriately). Of  
course the most flexible would be mapping a Proc#call - do  
whatever you want in that Proc.

To get maximum benefit from duck-typing, several things will  
help out:

\* For every duck-typed argument, document what the duck-type is  
- what methods it needs to respond to and what the duck-type  
requirements are on those method arguments and return values.  
To help out with this it would be nice if we had something in  
rdoc for this - but I don't know what.

\* A convenient way to create objects on-the-fly for duck-typed  
arguments. Some implementations were given in the thread  
"making a duck".

\* Don't overload your methods. As soon as you overload a  
method to allow multiple "types" for an argument (and do  
different things based on the "type"), you are not doing strict  
duck-typing. At a minimum when you overload, you have to ask  
whether an object responds to a certain method to determine  
what to do. Doing this can limit what you can pass in due to  
ambiguities as to what the "type" is. If you make a method  
that can take a flying-thing, a swimming-thing, or a  
walking-thing, what should this method do when it receives a  
duck - because a duck can fly, swim, and walk?

\* The fewer methods that a duck-typed argument responds to the  
more flexibility you have in what you can pass to to it. Many  
arguments may just require one method of the argument which is  
ideal (next to zero methods of course). One method allows easy  
on-the-fly object creation as described above.

\* Use duck-typing everywhere!

> **···**
>
> \_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_  
> Discover Yahoo!  
> Have fun online with music videos, cool games, IM and more. Check it out!  
> [http://discover.yahoo.com/online.html](http://discover.yahoo.com/online.html)

---

<div class="post-metadata">

**Author:** ![Robert](https://avatars.discourse-cdn.com/v4/letter/r/e95f7d/32.png) [@Robert](https://rubytalk.org/u/Robert)\
**Post date:** [10 June 2005 11:55 UTC](https://rubytalk.org/t/duck-typing-allows-deeper-polymorphism/18892/2 "2005-06-10T11:55:28Z")

</div>

Eric Mahurin wrote:

\<snip\>a lot of good stuff\</snip\>

> \* Use duck-typing everywhere!

Well quacked! 😉

Kind regards

&nbsp;&nbsp;&nbsp;&nbsp;robert

---

<div class="post-metadata">

**Author:** ![Ara.T.Howard6](https://avatars.discourse-cdn.com/v4/letter/a/958977/32.png) [@Ara.T.Howard6](https://rubytalk.org/u/Ara.T.Howard6)\
**Post date:** [10 June 2005 14:00 UTC](https://rubytalk.org/t/duck-typing-allows-deeper-polymorphism/18892/3 "2005-06-10T14:00:03Z")

</div>

\<snip good comments\>

i've had many of the same thoughts and tried to address them as simply as  
possible in my parseargs module

> To get maximum benefit from duck-typing, several things will  
> help out:
> 
> \* For every duck-typed argument, document what the duck-type is - what  
> methods it needs to respond to and what the duck-type requirements are on  
> those method arguments and return values. To help out with this it would be  
> nice if we had something in rdoc for this - but I don't know what.

this shows, right up front in the method, that the method takes an argument 'x'  
which must respond to 'upcase', and 'downcase'. an exception is thrown if  
something that does not respond to both these methods is passed in:

&nbsp;&nbsp;&nbsp;harp:~ \> cat a.rb  
&nbsp;&nbsp;&nbsp;require 'parseargs'  
&nbsp;&nbsp;&nbsp;include ParseArgs

&nbsp;&nbsp;&nbsp;def method(\*argv)  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;pa = parseargs(argv){  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;arg :x, :ducktype =\> %w(upcase downcase)  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;p pa.x.upcase.downcase  
&nbsp;&nbsp;&nbsp;end

&nbsp;&nbsp;&nbsp;method '42'

&nbsp;&nbsp;&nbsp;harp:~ \> ruby a.rb  
&nbsp;&nbsp;&nbsp;"42"

note that this could be parsed via rdoc quite easily.

> \* A convenient way to create objects on-the-fly for duck-typed  
> arguments. Some implementations were given in the thread  
> "making a duck".

two ways exist to do this easily using parseargs:

\* coerce the object into another type

&nbsp;&nbsp;&nbsp;harp:~ \> cat a.rb  
&nbsp;&nbsp;&nbsp;require 'parseargs'  
&nbsp;&nbsp;&nbsp;include ParseArgs

&nbsp;&nbsp;&nbsp;def method(\*argv)  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;pa = parseargs(argv){  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ra :x, :ducktype =\> %w(upcase downcase), 'coerce' =\> 'to\_s'  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;p pa.x.upcase.downcase  
&nbsp;&nbsp;&nbsp;end

&nbsp;&nbsp;&nbsp;method 42.0  
&nbsp;&nbsp;&nbsp;harp:~ \> ruby a.rb  
&nbsp;&nbsp;&nbsp;"42.0"

\* 'convince' the object that it can behave like a duck by extending on the fly

&nbsp;&nbsp;&nbsp;harp:~ \> cat a.rb  
&nbsp;&nbsp;&nbsp;require 'parseargs'  
&nbsp;&nbsp;&nbsp;include ParseArgs

&nbsp;&nbsp;&nbsp;def method(\*argv)  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;pa = parseargs(argv){  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ra :x,  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;:ducktype =\> %w(upcase downcase),  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;:convince =\> lambda{|obj|  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;class \<\< obj  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;def upcase; '42'; end  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;def downcase; '42'; end  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;p pa.x.upcase.downcase  
&nbsp;&nbsp;&nbsp;end

&nbsp;&nbsp;&nbsp;method Object::new

&nbsp;&nbsp;&nbsp;harp:~ \> ruby a.rb  
&nbsp;&nbsp;&nbsp;"42"

or via a module which should extend the object on the fly for increased  
duck-i-ness:

&nbsp;&nbsp;&nbsp;harp:~ \> cat a.rb  
&nbsp;&nbsp;&nbsp;require 'parseargs'  
&nbsp;&nbsp;&nbsp;include ParseArgs

&nbsp;&nbsp;&nbsp;module Ducky  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;def upcase; '42'; end  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;def downcase; '42'; end  
&nbsp;&nbsp;&nbsp;end

&nbsp;&nbsp;&nbsp;def method(\*argv)  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;pa = parseargs(argv){  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ra :x,  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;:ducktype =\> %w(upcase downcase),  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;:convince =\> Ducky  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;p pa.x.upcase.downcase  
&nbsp;&nbsp;&nbsp;end

&nbsp;&nbsp;&nbsp;method Object::new

&nbsp;&nbsp;&nbsp;harp:~ \> ruby a.rb  
&nbsp;&nbsp;&nbsp;"42"

> \* Use duck-typing everywhere!

hear hear!

cheers.

-a

> **···**
>
> # On Fri, 10 Jun 2005, Eric Mahurin wrote: --
> 
> > email :: ara [dot] t [dot] howard [at] noaa [dot] gov  
> > phone :: 303.497.6469  
> > My religion is very simple. My religion is kindness.  
> > --Tenzin Gyatso
> 
> ===============================================================================

---

<div class="post-metadata">

**Author:** ![Adam\_Sanderson](https://avatars.discourse-cdn.com/v4/letter/a/2acd7d/32.png) [@Adam\_Sanderson](https://rubytalk.org/u/Adam_Sanderson)\
**Post date:** [14 June 2005 17:10 UTC](https://rubytalk.org/t/duck-typing-allows-deeper-polymorphism/18892/4 "2005-06-14T17:10:32Z")

</div>

I was thinking perhaps you can define your duck types, ie:  
READABLE = [:open, :read]  
SORTABLE = ['\<=\>'.to\_sym]

Then extend Object a little:  
class Object  
&nbsp;&nbsp;def implements?(symbols)  
&nbsp;&nbsp;&nbsp;&nbsp;symbols.all?{|s| respond\_to? s}  
&nbsp;&nbsp;end  
end

It makes your types easily documented, and it's trivial to test if  
something implements the needed functionality.  
"hello".implements? SORTABLE  
=\> true  
"hello".implements? READABLE  
=\> false

I'm not really a big fan of this style, but it might be handy to  
someone 😉  
&nbsp;&nbsp;.adam sanderson

Eric Mahurin wrote:

> **···**
>
> > I've seen many posts on what duck-typing is, that Ruby doesn't  
> > need static typing, that duck-typing results in easy to read  
> > code, etc (and others that want static typing). What I haven't  
> > seen much of is what advantage duck-typing gives to a method  
> > over conventional polymorphism. This is a follow on of my  
> > previous thread "making a duck". I would like to get on my  
> > soapbox and talk about it a little...
> > 
> > With the polymorphism of other languages, class hierarchy is  
> > very important. When you specify an argument can take a  
> > certain class, you are saying that it can also take anything  
> > derived from it (or implementing the same interface if the  
> > language has that concept).
> > 
> > With duck-typing, class hierarchy and class names are not  
> > important. Every argument that is duck-typed (built-in methods  
> > unfortunately usually aren't) effectively has its own "type".  
> > The "type" of an argument is defined by what methods it needs  
> > to respond to and any "type" requirements of those methods  
> > arguments or return values. If an argument has no method  
> > requirements, then that argument could be anything. With an  
> > argument needs to respond to just one method, you can think  
> > about making an object on-the-fly that meets that one  
> > requirement. That one method could easily be made from a  
> > method of another object - including Proc#call (arbitrary  
> > code). With an argument that needs to respond to more methods,  
> > you can still do the same (mapping multiple methods), but at a  
> > certain point it may become too cumbersome.
> > 
> > As an example, suppose you have 2 methods in an object that  
> > take String-like things. With conventional polymorphism, you  
> > might abstract this up to anything indexable to encompass  
> > String and Array. With duck typing, you don't need to do  
> > anything explicit - just continue thinking of it like a String  
> > when coding the methods. Let's say one of the methods reads  
> > from its "String" argument using only the method. You could  
> > easily use a String, Array, Hash, or more powerfully a Proc.  
> > The second appends to its "String" argument using the \<\<  
> > method. Here you could easily use a String or Array. In both  
> > of these cases, you could grab any method of any object and map  
> > it to new object (and name the method appropriately). Of  
> > course the most flexible would be mapping a Proc#call - do  
> > whatever you want in that Proc.
> > 
> > To get maximum benefit from duck-typing, several things will  
> > help out:
> > 
> > \* For every duck-typed argument, document what the duck-type is  
> > - what methods it needs to respond to and what the duck-type  
> > requirements are on those method arguments and return values.  
> > To help out with this it would be nice if we had something in  
> > rdoc for this - but I don't know what.
> > 
> > \* A convenient way to create objects on-the-fly for duck-typed  
> > arguments. Some implementations were given in the thread  
> > "making a duck".
> > 
> > \* Don't overload your methods. As soon as you overload a  
> > method to allow multiple "types" for an argument (and do  
> > different things based on the "type"), you are not doing strict  
> > duck-typing. At a minimum when you overload, you have to ask  
> > whether an object responds to a certain method to determine  
> > what to do. Doing this can limit what you can pass in due to  
> > ambiguities as to what the "type" is. If you make a method  
> > that can take a flying-thing, a swimming-thing, or a  
> > walking-thing, what should this method do when it receives a  
> > duck - because a duck can fly, swim, and walk?
> > 
> > \* The fewer methods that a duck-typed argument responds to the  
> > more flexibility you have in what you can pass to to it. Many  
> > arguments may just require one method of the argument which is  
> > ideal (next to zero methods of course). One method allows easy  
> > on-the-fly object creation as described above.
> > 
> > \* Use duck-typing everywhere!
> > 
> > \_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_  
> > Discover Yahoo!  
> > Have fun online with music videos, cool games, IM and more. Check it out!  
> > [http://discover.yahoo.com/online.html](http://discover.yahoo.com/online.html)

---

<div class="post-metadata">

**Author:** ![Eric\_Mahurin1](https://avatars.discourse-cdn.com/v4/letter/e/34f0e0/32.png) [@Eric\_Mahurin1](https://rubytalk.org/u/Eric_Mahurin1)\
**Post date:** [10 June 2005 15:07 UTC](https://rubytalk.org/t/duck-typing-allows-deeper-polymorphism/18892/5 "2005-06-10T15:07:03Z")

</div>

> \> To get maximum benefit from duck-typing, several things  
> will  
> \> help out:  
> \>  
> \> \* For every duck-typed argument, document what the  
> duck-type is - what  
> \> methods it needs to respond to and what the duck-type  
> requirements are on  
> \> those method arguments and return values. To help out with  
> this it would be  
> \> nice if we had something in rdoc for this - but I don't  
> know what.
> 
> this shows, right up front in the method, that the method  
> takes an argument 'x'  
> which must respond to 'upcase', and 'downcase'. an exception  
> is thrown if  
> something that does not respond to both these methods is  
> passed in:
> 
> &nbsp;&nbsp;&nbsp;harp:~ \> cat a.rb  
> &nbsp;&nbsp;&nbsp;require 'parseargs'  
> &nbsp;&nbsp;&nbsp;include ParseArgs
> 
> &nbsp;&nbsp;&nbsp;def method(\*argv)  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;pa = parseargs(argv){  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;arg :x, :ducktype =\> %w(upcase downcase)  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;p pa.x.upcase.downcase  
> &nbsp;&nbsp;&nbsp;end
> 
> &nbsp;&nbsp;&nbsp;method '42'
> 
> &nbsp;&nbsp;&nbsp;harp:~ \> ruby a.rb  
> &nbsp;&nbsp;&nbsp;"42"
> 
> note that this could be parsed via rdoc quite easily.

I don't really like this because:

a. if you put this all over the place, it will significantly  
degrade the code readability

b. efficiency. You've added unnecessary checking. Why not let  
the code raise the exception when it doesn't find the method?

c. this may actually hinder some duck typing. In your example  
above, you might make the method not always call both upcase  
and downcase (maybe another boolean arg might control that).  
If the caller has enough control, he could call the method with  
an object that just responds to one of them. But parseargs  
unnecessarily prohibit that.

d. this only starts to capture the true duck-type. To really  
describe it, you would need a more elaborate system which  
included conditions when the arguments methods are called,  
description of the requirements for the arguments to those  
methods, and what the duck-type should be for return values of  
those methods. If you are able to implement that, then you  
really are going to make the first problem even worse - code  
clutter.

I think the description of the duck-type only belongs in the  
documentation. I don't really see the advantage of putting it  
in the code.

> \> \* A convenient way to create objects on-the-fly for  
> duck-typed  
> \> arguments. Some implementations were given in the thread  
> \> "making a duck".
> 
> two ways exist to do this easily using parseargs:
> 
> \* coerce the object into another type
> 
> &nbsp;&nbsp;&nbsp;harp:~ \> cat a.rb  
> &nbsp;&nbsp;&nbsp;require 'parseargs'  
> &nbsp;&nbsp;&nbsp;include ParseArgs
> 
> &nbsp;&nbsp;&nbsp;def method(\*argv)  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;pa = parseargs(argv){  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ra :x, :ducktype =\> %w(upcase downcase), 'coerce' =\>  
> 'to\_s'  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;p pa.x.upcase.downcase  
> &nbsp;&nbsp;&nbsp;end
> 
> &nbsp;&nbsp;&nbsp;method 42.0  
> &nbsp;&nbsp;&nbsp;harp:~ \> ruby a.rb  
> &nbsp;&nbsp;&nbsp;"42.0"
> 
> \* 'convince' the object that it can behave like a duck by  
> extending on the fly
> 
> &nbsp;&nbsp;&nbsp;harp:~ \> cat a.rb  
> &nbsp;&nbsp;&nbsp;require 'parseargs'  
> &nbsp;&nbsp;&nbsp;include ParseArgs
> 
> &nbsp;&nbsp;&nbsp;def method(\*argv)  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;pa = parseargs(argv){  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ra :x,  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;:ducktype =\> %w(upcase downcase),  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;:convince =\> lambda{|obj|  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;class \<\< obj  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;def upcase; '42'; end  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;def downcase; '42'; end  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;p pa.x.upcase.downcase  
> &nbsp;&nbsp;&nbsp;end
> 
> &nbsp;&nbsp;&nbsp;method Object::new
> 
> &nbsp;&nbsp;&nbsp;harp:~ \> ruby a.rb  
> &nbsp;&nbsp;&nbsp;"42"
> 
> or via a module which should extend the object on the fly for  
> increased  
> duck-i-ness:
> 
> &nbsp;&nbsp;&nbsp;harp:~ \> cat a.rb  
> &nbsp;&nbsp;&nbsp;require 'parseargs'  
> &nbsp;&nbsp;&nbsp;include ParseArgs
> 
> &nbsp;&nbsp;&nbsp;module Ducky  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;def upcase; '42'; end  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;def downcase; '42'; end  
> &nbsp;&nbsp;&nbsp;end
> 
> &nbsp;&nbsp;&nbsp;def method(\*argv)  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;pa = parseargs(argv){  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ra :x,  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;:ducktype =\> %w(upcase downcase),  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;:convince =\> Ducky  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;p pa.x.upcase.downcase  
> &nbsp;&nbsp;&nbsp;end
> 
> &nbsp;&nbsp;&nbsp;method Object::new
> 
> &nbsp;&nbsp;&nbsp;harp:~ \> ruby a.rb  
> &nbsp;&nbsp;&nbsp;"42"

I'm talking about the caller making the duck, not the method  
being called. Something like this:

# make call act like xyz for this new arg  
method\_where\_arg\_responds\_to\_xyz( proc{...}.duck(:xyz,:call) )

> \> \* Use duck-typing everywhere!
> 
> hear hear!

I guess I really should have said "use pure duck-typing  
everywhere". What I mean by that is that methods shouldn't try  
to categorize or test the capabilities of their arguments at  
all - don't use #respond\_to?, #class, etc. I used to use  
#respond\_to? occassionally to make overloaded methods, but am  
now convinced to go the pure duck-typing route - splitting  
overloaded methods into multiple methods.

> **···**
>
> --- "Ara.T.Howard" \<Ara.T.Howard@noaa.gov\> wrote:
> 
> > On Fri, 10 Jun 2005, Eric Mahurin wrote:
> 
> \_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_  
> Discover Yahoo!  
> Have fun online with music videos, cool games, IM and more. Check it out!  
> [http://discover.yahoo.com/online.html](http://discover.yahoo.com/online.html)

---

<div class="post-metadata">

**Author:** ![Ara.T.Howard6](https://avatars.discourse-cdn.com/v4/letter/a/958977/32.png) [@Ara.T.Howard6](https://rubytalk.org/u/Ara.T.Howard6)\
**Post date:** [10 June 2005 17:04 UTC](https://rubytalk.org/t/duck-typing-allows-deeper-polymorphism/18892/6 "2005-06-10T17:04:09Z")

</div>

> I don't really like this because:
> 
> a. if you put this all over the place, it will significantly  
> degrade the code readability

i strongly disagree here. in the case of short examples it is roughly  
equivalent

&nbsp;&nbsp;&nbsp;def method argv  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;pa = parseargs(argv){  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;required\_argument 'a'  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;optional\_argument 'b'  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}  
&nbsp;&nbsp;&nbsp;end

four lines

&nbsp;&nbsp;&nbsp;def method a, b  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@a = a  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@b = b  
&nbsp;&nbsp;&nbsp;end

two lines

in the real world, in case where you might actually use parseages, it will  
shine

&nbsp;&nbsp;&nbsp;TWENTY\_SIX\_KEWORDS\_AT\_ONCE = ('a' .. 'z').to\_a

&nbsp;&nbsp;&nbsp;def method argv  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;pa = parsearges(argv){  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;required\_argument 'foobar'  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;keywords TWENTY\_SIX\_KEWORDS\_AT\_ONCE  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}  
&nbsp;&nbsp;&nbsp;end

four lines

now, if you write some loop that accepts all those kewords and loads them into  
a hash, openstruct, or something - and does not allow any other keywords,  
raising an ArgumentError if they are passed in, and then you duplicate this in  
all the methods that have that kind of logic, your code will be at least 10  
time more verbose and obfusicated.

essentially your comment is like saying

&nbsp;&nbsp;&nbsp;help = (ARGV.include? '-h' or ARGV.include? '--help')

is better/more readable than using optparse or getoplong. true if that's all  
you are doing (for instance in an example) - otherwise severely false.

another example

&nbsp;&nbsp;&nbsp;class CascadingStyleSheet  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;class Element  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;FontProperties = %w(  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;font-family  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;font-style  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;font-variant  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;font-weight  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;font-size  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;font  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;)  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ColorAndBackgroundProperties = %w(  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;color  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;background-color  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;background-image  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;background-repeat  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;...  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;)  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;TextProperties = %w(  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;...  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;)  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;BoxProperties = %w(  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;...  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;)  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ClassificationProperties = %w(  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;...  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;)

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;CSSProperties = FontProperties + ColorAndBackgroundProperties +  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;TextProperties + BoxProperties + ClassificationProperties

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;attr 'selector'

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;CSSProperties.each{|prop| attr prop}

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;def initialize argv  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;pa = parseargs(argv) {  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;required\_argument 'selector'  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;keywords CSSProperties  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.selector = pa.selector

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;CSSProperties.each{|prop| send prop, pa.prop}  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;def font\_configure argv  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;pa = parseargs(argv) {  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;keywords FontProperties  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;...  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;def box\_configure  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;pa = parseargs(argv) {  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;keywords FontProperties  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;...  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end  
&nbsp;&nbsp;&nbsp;end

it's this kind of code that spirals out of control with rampant DRY violations  
unless parseargs or a roll-your-own type argv parsing scheme is devised.

> b. efficiency. You've added unnecessary checking. Why not let  
> the code raise the exception when it doesn't find the method?

it's only added if you like. you don't have to use the duck-typing feature at  
all. besides, you approach is simply not valid for some cases (like nearly  
all the code i have around here) that do things like

&nbsp;&nbsp;&nbsp;def method job, logger

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;job.submit\_job\_to\_queue\_that\_takes\_three\_to\_five\_days

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;logger.info{ "job \<#{ job.name }\> finished with \<#{ job.status }\>"

&nbsp;&nbsp;&nbsp;end

now, if logger doesn't repsond to 'info' or job doesn't respond to 'name' and  
'status' i'll blow up and not log a job that just took three days to run.  
bummer.

> c. this may actually hinder some duck typing. In your example above, you  
> might make the method not always call both upcase and downcase (maybe  
> another boolean arg might control that). If the caller has enough control,  
> he could call the method with an object that just responds to one of them.  
> But parseargs unnecessarily prohibit that.

again - it's \_\_experimental\_\_. these kinds of comments are great and  
precisely what this group is best at.

> d. this only starts to capture the true duck-type.

absolutely true. remember - it's an arg parsing module not a duck typing  
toolset.

> To really describe it, you would need a more elaborate system which included  
> conditions when the arguments methods are called, description of the  
> requirements for the arguments to those methods, and what the duck-type  
> should be for return values of those methods.

absolutely. there are several attempts on the RAA.

> If you are able to implement that, then you really are going to make the  
> first problem even worse - code clutter.

which is is why i chose to implement the simplest possible thing that could  
work and which covers the most common usage. at the very least it's something  
people might be able to build upon.

> I think the description of the duck-type only belongs in the documentation.  
> I don't really see the advantage of putting it in the code.

three days - banking transactions - remote method invocations... there are  
tons of scenarios where you need to either know your object can do such and  
such or try to make it if does not because each attempt is expensive in terms  
of disk, cpu, or network. it's luxurious to be able to write code that can  
just crash or be run again - but it's not always possible.

> > hear hear!
> 
> I guess I really should have said "use pure duck-typing everywhere". What I  
> mean by that is that methods shouldn't try to categorize or test the  
> capabilities of their arguments at all - don't use #respond\_to?, #class,  
> etc. I used to use #respond\_to? occassionally to make overloaded methods,  
> but am now convinced to go the pure duck-typing route - splitting overloaded  
> methods into multiple methods.

again - this notion ignores all notion of temporality and cost. what if you  
were paying for a slot on a super-computer and wouldn't be able to get in  
again for three weeks and had a pending paper due?

cheers.

-a

> **···**
>
> # On Sat, 11 Jun 2005, Eric Mahurin wrote: --
> 
> > email :: ara [dot] t [dot] howard [at] noaa [dot] gov  
> > phone :: 303.497.6469  
> > My religion is very simple. My religion is kindness.  
> > --Tenzin Gyatso
> 
> ===============================================================================

---

<div class="post-metadata">

**Author:** ![Eric\_Mahurin1](https://avatars.discourse-cdn.com/v4/letter/e/34f0e0/32.png) [@Eric\_Mahurin1](https://rubytalk.org/u/Eric_Mahurin1)\
**Post date:** [10 June 2005 17:51 UTC](https://rubytalk.org/t/duck-typing-allows-deeper-polymorphism/18892/7 "2005-06-10T17:51:06Z")

</div>

> &nbsp;&nbsp;&nbsp;TWENTY\_SIX\_KEWORDS\_AT\_ONCE = ('a' .. 'z').to\_a
> 
> &nbsp;&nbsp;&nbsp;def method argv  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;pa = parsearges(argv){  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;required\_argument 'foobar'  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;keywords TWENTY\_SIX\_KEWORDS\_AT\_ONCE  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}  
> &nbsp;&nbsp;&nbsp;end

I could see this being useful. But, I don't care for  
additional "type" checking over what the code already does.

> \> b. efficiency. You've added unnecessary checking. Why not  
> let  
> \> the code raise the exception when it doesn't find the  
> method?
> 
> it's only added if you like. you don't have to use the  
> duck-typing feature at  
> all. besides, you approach is simply not valid for some  
> cases (like nearly  
> all the code i have around here) that do things like
> 
> &nbsp;&nbsp;&nbsp;def method job, logger
> 
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;job.submit\_job\_to\_queue\_that\_takes\_three\_to\_five\_days
> 
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;logger.info{ "job \<#{ job.name }\> finished with \<#{  
> job.status }\>"
> 
> &nbsp;&nbsp;&nbsp;end
> 
> now, if logger doesn't repsond to 'info' or job doesn't  
> respond to 'name' and  
> 'status' i'll blow up and not log a job that just took three  
> days to run.  
> bummer.

So you just want the check to occur earlier than when the code  
makes the check. That sounds like a reasonable usage when the  
method can take a very long time (\> a few minutes).

> \>\> hear hear!  
> \>  
> \> I guess I really should have said "use pure duck-typing  
> everywhere". What I  
> \> mean by that is that methods shouldn't try to categorize or  
> test the  
> \> capabilities of their arguments at all - don't use  
> #respond\_to?, #class,  
> \> etc. I used to use #respond\_to? occassionally to make  
> overloaded methods,  
> \> but am now convinced to go the pure duck-typing route -  
> splitting overloaded  
> \> methods into multiple methods.
> 
> again - this notion ignores all notion of temporality and  
> cost. what if you  
> were paying for a slot on a super-computer and wouldn't be  
> able to get in  
> again for three weeks and had a pending paper due?

Maybe you could think of duck-typing as when functionally a  
method doesn't need to categorize the "type" of any of its  
arguments or overconstrain what its argument capabilities  
should be. Implementation-wise, you may use respond\_to?,  
class, etc but it should have equivalent functionality to some  
implementation that didn't use these. I think this early  
checking you do would just be an implementation thing. Another  
case I can think of is when you might have a more efficient  
(i.e. C) implementation for a specific class. For example, if  
you wanted to make a duck-typed Regexp class, you might special  
case the String class:

def Regexp  
def match(sequence)  
&nbsp;&nbsp;&nbsp;&nbsp;if String===sequence  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;super # fast C implementation  
&nbsp;&nbsp;&nbsp;&nbsp;else  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;# a less efficient pure duck-typed implementation  
&nbsp;&nbsp;&nbsp;&nbsp;end  
end  
end

I think it would be great if more of the built-in classes were  
duck-typed like this.

> **···**
>
> --- "Ara.T.Howard" \<Ara.T.Howard@noaa.gov\> wrote:
> 
> \_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_  
> Discover Yahoo!  
> Find restaurants, movies, travel and more fun for the weekend. Check it out!  
> [http://discover.yahoo.com/weekend.html](http://discover.yahoo.com/weekend.html)

---

<div class="post-metadata">

**Author:** ![Ara.T.Howard6](https://avatars.discourse-cdn.com/v4/letter/a/958977/32.png) [@Ara.T.Howard6](https://rubytalk.org/u/Ara.T.Howard6)\
**Post date:** [10 June 2005 18:30 UTC](https://rubytalk.org/t/duck-typing-allows-deeper-polymorphism/18892/8 "2005-06-10T18:30:08Z")

</div>

> > &nbsp;&nbsp;&nbsp;TWENTY\_SIX\_KEWORDS\_AT\_ONCE = ('a' .. 'z').to\_a
> > 
> > &nbsp;&nbsp;&nbsp;def method argv  
> > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;pa = parsearges(argv){  
> > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;required\_argument 'foobar'  
> > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;keywords TWENTY\_SIX\_KEWORDS\_AT\_ONCE  
> > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}  
> > &nbsp;&nbsp;&nbsp;end
> 
> I could see this being useful. But, I don't care for  
> additional "type" checking over what the code already does.

well, me too for the most part and i rarely use the the :type/:ducktype  
options myself - but i do use them at times...

> So you just want the check to occur earlier than when the code  
> makes the check. That sounds like a reasonable usage when the  
> method can take a very long time (\> a few minutes).

exactly. i end up with stuff like that alot around here...

> Maybe you could think of duck-typing as when functionally a method doesn't  
> need to categorize the "type" of any of its arguments or overconstrain what  
> its argument capabilities should be. Implementation-wise, you may use  
> respond\_to?, class, etc but it should have equivalent functionality to some  
> implementation that didn't use these. I think this early checking you do  
> would just be an implementation thing. Another case I can think of is when  
> you might have a more efficient (i.e. C) implementation for a specific  
> class.

this seems more or less correct... i haven't considered it quite that way.

> class. For example, if you wanted to make a duck-typed Regexp class, you  
> might special case the String class:
> 
> def Regexp  
> def match(sequence)  
> &nbsp;&nbsp;&nbsp;if String===sequence  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;super # fast C implementation  
> &nbsp;&nbsp;&nbsp;else  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;# a less efficient pure duck-typed implementation  
> &nbsp;&nbsp;&nbsp;end  
> end
> 
> I think it would be great if more of the built-in classes were duck-typed  
> like this.

at first glance this sounds o.k. - but i think i would lead to many sublte  
errors like we see in perl. that may sound like i'm contra-dicting myself;  
after all, i use duck typing all the time. but there is a big difference  
between user written code and language level libs : namely that i know with  
great certainty the environment much of my code runs in. for instance i might  
know that only i will ever use it 😉 that's not the case with built-ins  
though and i, for one, am glad '0' will never act like 0. i conceed that  
there are some cases where it would might make sense though - it should just  
be considered very very carefully for core code.

cheers.

-a

> **···**
>
> On Sat, 11 Jun 2005, Eric Mahurin wrote:
> 
> > --- "Ara.T.Howard" \<Ara.T.Howard@noaa.gov\> wrote:
> 
> # --
> 
> > email :: ara [dot] t [dot] howard [at] noaa [dot] gov  
> > phone :: 303.497.6469  
> > My religion is very simple. My religion is kindness.  
> > --Tenzin Gyatso
> 
> ===============================================================================
