Hi -- On Tue, 14 Aug 2007, Nasir Khan wrote: > Thanks to all the respondents. > The confusion stemmed from some of the inconsistency that is around the > to_str usage within Ruby. > > See this below. > > class A > def to_str > "hello" > end > def to_s > "bye" > end > end > > # Note to_s and to_str return different strings. > > irb(main):018:0> "xyz"+A.new > => "xyzhello" > > Good, as to_str is called when it is 'expected' that arg to + is going to be > a string. > > irb(main):019:0> "hello" == A.new > => false > > This is fine too as David pointed out, one could argue though because there > already is a equal? but anyway....lets move on. I'm digging around in the source to figure out the == behavior. Here's the method: static VALUE rb_str_equal(str1, str2) VALUE str1, str2; { if (str1 == str2) return Qtrue; if (TYPE(str2) != T_STRING) { if (!rb_respond_to(str2, rb_intern("to_str"))) { return Qfalse; } return rb_equal(str2, str1); } if (RSTRING(str1)->len == RSTRING(str2)->len && rb_str_cmp(str1, str2) == 0) { return Qtrue; } return Qfalse; } I haven't quite figured out what the point is of testing to see whether str2 responds to "to_str", since even if it does, to_str isn't called. But I might just have to keep following the trail.... > Then see > > irb(main):020:0> A.new.upcase > NoMethodError: undefined method `upcase' for hello:A > from (irb):20 > > Again since A.new is not a String a method_missing is called etc. > > Bear with me a little more :-) > > irb(main):021:0> "hellooo".include? A.new > => true > > This is good because the argument is expected to be a string. I believe the to_str thing is always about arguments. The object A.new is not just going to act like a string; you can't call String instance methods on it (like upcase). It's only going to provide its to_str representation when it's an argument, as in include? . > Now see this > > irb(main):022:0> "a" << A.new > => "ahello" > OK so now Ruby used the string representation from to_str *not* to_s > Now is it true that *only* object of class String are expected to be > appended to a string using << operator, hence the coercion? > > Not quite - > > irb(main):023:0> "a" << 1 > => "a\001" > > While of course - > irb(main):025:0> 1.to_str > NoMethodError: undefined method `to_str' for 1:Fixnum > > But of course - > irb(main):038:0> 1.to_s > => "1" > > So is it the case that when a string is "expected" then a to_str is tried if > not found then to_s is tried, as can be deduced from the last two operations > above? But then of course the following would fail - It's not exactly that. Have a look at this and you'll see: irb(main):004:0> "abc" << 1 => "abc\001" irb(main):005:0> "abc" << 100 => "abcd" irb(main):006:0> "abc" << 10 => "abc\n" This operation doesn't involve to_s or to_str, so it doesn't tell you anything about how they work. Your next example answers the question, though: to_s does not serve as a fall-back for to_str. David -- * Books: RAILS ROUTING (new! http://www.awprofessional.com/title/0321509242) RUBY FOR RAILS (http://www.manning.com/black) * Ruby/Rails training & consulting: Ruby Power and Light, LLC (http://www.rubypal.com)