To_s and concatenation

rasputin@shrike rasputin$ irb
irb(main):001:0> class Wtf
irb(main):002:1> def to_s
irb(main):003:2> 'fnord’
irb(main):004:2> end
irb(main):005:1> end
=> nil
irb(main):006:0>
irb(main):007:0* puts "#{Wtf.new}"
fnord
=> nil
irb(main):008:0> puts Wtf.new
fnord
=> nil
irb(main):009:0> puts "foo #{Wtf.new}"
foo fnord
=> nil
irb(main):010:0> puts “foo” + Wtf.new
TypeError: failed to convert Wtf into String
from (irb):10:in `+'
from (irb):10
irb(main):011:0> exit

How come one works and the other doesn’t? Is it a precedence thing?

···


Rasputin :: Jack of All Trades - Master of Nuns

irb(main):010:0> puts "foo" + Wtf.new
TypeError: failed to convert Wtf into String

String#+ want an object which respond to #to_str

Guy Decoux

irb(main):010:0> puts “foo” + Wtf.new
TypeError: failed to convert Wtf into String

String#+ want an object which respond to #to_str

Right, but when do you use one and when the other?
Pickaxe says:

to_str str.to_str → str

Synonym for String#to_s . to_str is used by methods such as
String#concat to convert their arguments to a string. Unlike to_s, which
is supported by almost all classes, to_str is normally implemented only
by those classes that act like strings. Of the built-in classes, only
Exception and String implement to_str.

supports what you just said (although the ‘synonym for’ sentence is a
bit misleading), but what else would you use to_s for but to
print to stdout?

I know this is probably basic stuff, but there doesn’t seem to be
anywhere else to ask…

···


Rasputin :: Jack of All Trades - Master of Nuns

supports what you just said (although the 'synonym for' sentence is a
bit misleading), but what else would you use to_s for but to
print to stdout?

svg% ruby -e 'class A;def to_s()"A#object";end;end; p [A.new, "aa"].join(":")'"A#object:aa"
svg%

Guy Decoux

Interpolation into strings - “#{foo}” - uses to_s

Regards,

Brian.

···

On Sat, May 31, 2003 at 01:06:49AM +0900, Rasputin wrote:

Synonym for String#to_s . to_str is used by methods such as
String#concat to convert their arguments to a string. Unlike to_s, which
is supported by almost all classes, to_str is normally implemented only
by those classes that act like strings. Of the built-in classes, only
Exception and String implement to_str.

supports what you just said (although the ‘synonym for’ sentence is a
bit misleading), but what else would you use to_s for but to
print to stdout?

Brian Candler wrote:

···

On Sat, May 31, 2003 at 01:06:49AM +0900, Rasputin wrote:

Synonym for String#to_s . to_str is used by methods such as
String#concat to convert their arguments to a string. Unlike to_s, which
is supported by almost all classes, to_str is normally implemented only
by those classes that act like strings. Of the built-in classes, only
Exception and String implement to_str.

supports what you just said (although the ‘synonym for’ sentence is a
bit misleading), but what else would you use to_s for but to
print to stdout?

Interpolation into strings - “#{foo}” - uses to_s

Regards,

Brian.

hmm… it seems to me that the real question is this: why have both to_s
and to_str when the return value of them should at all concievable (to
me at least) times be the same?


dc -e
4ddod3dddn1-89danrn10-dan3+ann6dan2an13dn1+dn2-dn3+5ddan2/9+an13nap

I think the rationale is something like this:

You have a method for explicitly converting an object to a string for
display purposes:
5.to_s #>> “5”

But you might not want to have an automatic, implicit conversion to a
string in all circumstances:

"10" + 5      #>> should this be "105" or "15" or 15 ?
5 + "10"      #>> what about this: "510" or "15" or 15 ?

So I believe that to_s is for cases where you explicitly require a
conversion to be made, such as foo.to_s or “#{foo}”

On the other hand, to_str is for cases where an implicit, automatic
conversion should take place. If you don’t define it, then such automatic
conversions do not take place, so you get an exception instead.

irb(main):001:0> “10” + 5
TypeError: failed to convert Fixnum into String
from (irb):1:in +’
from (irb):1
irb(main):002:0> class Fixnum; def to_str; to_s; end; end
=> nil
irb(main):003:0> “10” + 5
=> “105”

The same distinction doesn’t seem to hold for to_int and to_i though - you
get a different exception. I don’t understand the mechanics of coercion of
numeric types.

Regards,

Brian.

···

On Sat, May 31, 2003 at 06:13:36AM +0900, Anders Borch wrote:

hmm… it seems to me that the real question is this: why have both to_s
and to_str when the return value of them should at all concievable (to
me at least) times be the same?

Hi –

···

On Sat, 31 May 2003, Brian Candler wrote:

The same distinction doesn’t seem to hold for to_int and to_i though - you
get a different exception. I don’t understand the mechanics of coercion of
numeric types.

Just one addendum: it does hold for to_a/to_ary – that is, you can
define to_ary on an object and that’s how the object will represent
itself in cases where an array is expected, while to_a will return
at least something for every object.

David


David Alan Black
home: dblack@superlink.net
work: blackdav@shu.edu
Web: http://pirate.shu.edu/~blackdav

hmm… it seems to me that the real question is this: why have both to_s
and to_str when the return value of them should at all concievable (to
me at least) times be the same?

Exactly, but I think Brians explanation makes sense to me now.
I wasa thrown by to_s/to_str in String being synonymous, whereas that’s
not the case in general. Thanks for the help.

···

On Sat, May 31, 2003 at 06:13:36AM +0900, Anders Borch wrote:

So I believe that to_s is for cases where you explicitly require a
conversion to be made, such as foo.to_s or “#{foo}”

On the other hand, to_str is for cases where an implicit, automatic
conversion should take place. If you don’t define it, then such automatic
conversions do not take place, so you get an exception instead.


Rasputin :: Jack of All Trades - Master of Nuns