From: Eric Hodel Date: 2006-08-09T04:24:18+09:00 Subject: Re: How to react on nil or wrong object-type as parameter On Aug 8, 2006, at 10:35 AM, Daniel Schierbeck wrote: > Eric Hodel wrote: >> On Aug 8, 2006, at 2:45 AM, Daniel Schierbeck wrote: >>> Eric Hodel wrote: >>>> On Aug 7, 2006, at 3:30 PM, Daniel Schierbeck wrote: >>>>> Eric Hodel wrote: >>>>>> On Aug 6, 2006, at 7:55 AM, Daniel Schierbeck wrote: >>>>>>> I'd do it like this: >>>>>>> >>>>>>> class SomeClass >>>>>>> def foo(obj) >>>>>>> str = obj.to_str >>>>>> Don't call to_str, call to_s. >>>>>>> puts str + str # or `str * 2' >>>>>>> puts str.reverse >>>>>>> end >>>>>>> end >>>>>>> >>>>>>> Though I know some very smart people on this list disagree >>>>>>> with me. >>>>>> Only because you call to_str. This is not the reason it exists. >>>>> >>>>> I favor using #to_str when I want to treat an object like a >>>>> string. Practically all classes implement #to_s, so it's not >>>>> really a type restriction. We're trying to solve two different >>>>> problems -- I want to let the caller know if he sent the wrong >>>>> kind of object as an argument. That's type checking. If you >>>>> want to convert any object received to a string, then we're >>>>> talking type conversion, which I think should be left to the >>>>> caller in many cases. But that's just my humble opinion, of >>>>> course. >>>> #to_str is not for type conversion. It exists for classes that >>>> duck type completely to String and is called when a C string is >>>> needed by a method in String to improve performance. In other >>>> words, #to_str should only be implemented on objects that are >>>> already "Strings". >>> >>> Exactly my point. I think we're misunderstanding each other here; >>> if you have an object that is a representation of a string, say >>> >>> # Bad example, but hey... >>> class Name >>> attr_accessor :first, :last >>> >>> def initialize(first, last) >>> @first, @last = first, last >>> end >>> end >>> >>> Then it's okay for it to have #to_str, e.g. >>> >>> def to_str >>> "#{first} #{second}" >>> end >>> >>> My own logic is this: if an object is a natural string, but with >>> *more* information, then it can have #to_str. Otherwise, stick to >>> #to_s. >> A Name is not a String. You don't #each it, you don't #chop it, >> its never #empty?, ... > > That's why you use the return value of #to_str. You don't call #to_str, String calls #to_str when it needs to. > If only String had #to_str, then why have it in the first place? > Why not just check the class? It would be appropriate to define #to_str for objects that really are Strings, but don't inherit from String. A good example would be when writing a bridge to another language, like Java strings or C# strings. > I'm not saying this is how everybody should do it, I'm just saying > that it's a very smart way to handle types -- duck typing being a > very similar way. It isn't a smart way to handle types, it is a broken and wrong way to handle types. Don't confuse "duck types to String" with "has a String representation (#to_s)". I doubt you will ever mean to say the former. -- Eric Hodel - drbrain@segment7.net - http://blog.segment7.net This implementation is HODEL-HASH-9600 compliant http://trackmap.robotcoop.com