I've been following the drama in this thread with great interest.

I tried to interject a thought a few days ago and it seems to have
fallen on deaf ears.

Let me try again.

The perceived 'need' for MI in Ruby comes from a
misunderstanding/ignorance of the difference of the meaning of
inheritance in languages like Ruby vs. languages like Java/C++.

In Java/C++ inheritance is primarily a means of expressing type
relationships, and secondarily a means of sharing implementation.
Because of the statically typed nature of these languages, related
types HAVE to be related by inheritance.

In Ruby, inheritance is solely a mechanism for sharing implementation.
 Inheritance in Ruby does not build a type hierarchy, even though it
might superficially appear to.

   1) It doesn't build a type hierarchy in the sense that two objects
which can be substituted for each other in a given context don't have
to have any kind of implementation relationship, the need only
correctly implement the set of behaviors required by the user.
   2) It doesn't build a type hierarcy because in general the whole
notion of types in Ruby is rather flexible, recall the discussion of
whether or not it was 'proper' to make ranges of floats.  Sometimes
range elements need to have a succ method, sometimes not, depending on
how you use the resulting Range.

In a statically typed language the coupling of type specification with
implementation leads to a particular set of pressures on the design of
both the language and programs in that language which are different
from the pressures on Ruby and it's programs.  Many of the things
which drove statically typed languages come from addressing problems
caused when compiled code which expected an object to be laid out in
memory a certain way ran across an object which had been miscast,
leading to run-time crashes, or hard to debug behavior.  Static typing
provides a mechanism to winnow out some of these bugs at compile time,
however most bugs in the development of any program are more subtle
and arise not from type but from logic errors.

Dynamic languages exhibit different failure behavior.  Executable code
is less sensitive to the bits and bytes layout, and the kind of errors
caught by static typing tend to fail faster at run-time with better
debugging information available at the time of failure.  The main
reason test-first techniques came out of the dynamic language
community was that it was a 'substitute' for static type checking
which actually covers a much broader spectrum of the kind of errors
programmers make.


I certainly understand how this flexibility and decoupling of the
notion of types from inheritance can seem wrong to one trained in
Java/C++ or the like, but the point is that these different
philosophies lead to different approaches to design.  Trying to bend
Ruby inheritance and mixins as a means of typing is working against
the strengths of the language, just as trying to manually simulate
dynamic binding in C++ is an indication that you aren't working with
your technology.

As the old maxim goes, "When in Rome..."

-- 
Rick DeNatale

My blog on Ruby
http://talklikeaduck.denhaven2.com/