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.