From: "bitsweat (Jeremy Kemper)" Date: 2012-11-14T12:40:10+09:00 Subject: [ruby-core:49333] [ruby-trunk - Bug #7342] String#<=> checks for a #to_str method on other but never uses it? Issue #7342 has been updated by bitsweat (Jeremy Kemper). When an object responds to #to_str, it's saying "I am a string." When an object responds to #to_s, it's saying "I have a string representation." So checking for #to_str here is enough to know whether str2 is a string and can be compared. For more background on implicit vs explicit coercion in Ruby: http://briancarper.net/blog/98/ ---------------------------------------- Bug #7342: String#<=> checks for a #to_str method on other but never uses it? https://bugs.ruby-lang.org/issues/7342#change-32891 Author: jballanc (Joshua Ballanco) Status: Open Priority: Normal Assignee: Category: Target version: ruby -v: 2.0.0 =begin This isn't exactly a bug, as much as a request for clarification. I was looking at the semantics of the (({<=>})) operator and noticed something curious. For most classes, when evaluating (({thing <=> other})), if (({other})) is not of a compatible type, then (({nil})) is returned. The exceptions (as far as I can find) are String and Time. For the Time class, if (({other})) is not a kind of (({Time})), then the reverse comparison (({other <=> thing})) is tried and the inverse of this result is returned (if not nil). For String, the reverse comparison is only tried IF (({other.respond_to?(:to_str)})), HOWEVER the referenced (({other.to_str})) method is never called. For example: class NotAString def <=>(other) 1 end def to_str raise "I'm not a string!" end end "test" <=> NotAString.new #=> -1 This seems very counterintuitive to me. I would expect that if my class implemented (({to_str})), that the return value of this would be used for comparison. =end -- http://bugs.ruby-lang.org/