From: Sam Roberts Date: 2005-03-14T06:40:57+09:00 Subject: Re: how do you duck-type something to String, so String believes you? Quoting ruby-ml@magical-cat.org, on Mon, Mar 14, 2005 at 04:12:24AM +0900: > On 3/13/2005, "Sam Roberts" wrote: > > >I can give something a #to_str, which should be an indication that it is > >duck-type compat to a String (as opposed to #to_s, which converts > >something to a String). > > > >That's all fine, but that doesn't mean that String will allow itself to > >be compared to my class: ... > >I can add as many methods as I want to String, I can even proxy every > >single method in it using #undefined_method (which is as duck-typed as > >you can get) but I still don't think a String object will ever "== => > >true" to my class. > > > >Am I right about this? > > If your class defines #to_str and #<==>, it should work. > String#== checks for #to_str, if that's OK, transfers to > String#<==> which checks for #to_str, if that's OK, transfers > to OtherClass#<==>. Then your #<==> must take a String and > compare it returning -1, 0 or 1. Did some playing around with this. What I see is that if you want: "somestr" == your_obj your_obj needs #to_str and #== (#<=> won't do it) "somestr" <=> your_obj your_obj needs #to_str and #<=> "somestr".eql?(your_obj) you can't do do this. So String will 'invert" == and <=> if the argument has a #to_str, but no other methods will be inverted. Do I understand correctly? Sam The code I played with: class Str def to_str; 'str'; end # def eql?(s); true; end # def ==(s); true; end def eql?(s); true; end # def <=>(s); 0; end end p Str.new == 'a' p 'a' == Str.new p Str.new.eql?('a') p 'a'.eql?(Str.new) p Str.new <=> 'a' p 'a' <=> Str.new