From: "Dave Thomas" <Dave / PragmaticProgrammer.com>
> "Tim Hunter" <cyclists / nc.rr.com> writes:
>
> > Q: I've defined a class whose objects may be ordered. What should
> > my <=> method do when the "other" argument is not in the same
> > class?
> >
> > A. Raise a TypeError exception.
>
> I have to say I disagree with this fairly strongly.
>
> > The <=> method in most of Ruby's
> > built-in classes will raise a TypeError exception if "other"
> > can't be coerced into the same class.
>
> There's a boat load of difference between coercion and "being the same
> class". For example, following your code example would mean that
>
>    1 <=> 1.2
>
> would raise a type error.
>
> [...]
>

These are good points, Dave (and David Black as well), and I do not disagree,
but I will point out that the counter-examples given are strongly in the domain
of built-in classes (i.e. String <=> Regexp, Integer <=> Float), and this is no
surprise: the classes built in to the langauge are obviously designed to work
together to a degree.

The FAQ is about user-defined classes, and I'll make the following points in
support of type-checking in the comparison operator:
 - things that can be compared are generally data objects more than behaviour
   objects
 - it is behaviour objects that are capable of masquerading, so the points
   raised by Davids would apply mostly to those
 - user-defined data objects are generally quite application-, or domain-
   specific
 - application- or domain-specific objects are *generally* not designed to
   be compared to built-ins or other user-defined objects [1]; obviously,
   exceptions exist and this should be noted
 - coercion between user-defined types is a rare thing, and the programmer
   would obviously make use of it in comparison if it exists
 - if the relationship between user-defined types is known (and it should be)
   why shouldn't it be encoded/enforced?
 - the price of *not* checking the class of the object to be compared is
   possibly calling methods that don't exist, or that do the "wrong" thing
   (e.g. consumed by method_missing)
 - the benefit of checking the class of the object to be compared is clearer
   error messages and prevention of doing The Wrong Thing
 - the cost of checking the class of the object to be compared, after
   considering all of the above, is ... what?

> Overzealously checking the class of parameters defeats much of the
> point of Ruby.
>
> Dave

To which I say "everything in moderation".  I perform class-checking on my
data-objects when I have considered all the above and conclude that there is no
good reason not to.  Comparison seems like an important part of program logic,
and I like to catch errors early.  Especially after modifying something -
comparison is something that happends "downstream", nowhere near the actual
modification.  Also, I like meaningful error messages where possible.

I also like Ruby's flexibility, so I don't overdo it, and take advantage of the
flexibility (at the risk of weird errors) when I can.

Cheers,
Gavin

PS. I don't know what this means for the FAQ.  A bit of discussion, I suppose.

[1] A user-defined data object would generally have several (N>2) fields.
Comparison with another object would generally involve most of these N fields.
Thus comparisons with built-in types (generally 1 field) are not meaningful
(again, exceptions exist, but they are exceptions).  Also, a different
user-defined object would only compare meaningfully if it was known to be
related in some way.