Difference between to_s and to_str

There has been some discussion on this topic in the thread “deciding
between ruby and python”. It was centered around how far #join should
go in getting what it wants (a String) from an object. I detected
some misunderstanding at the intention of #to_s and #to_str, so I hope
the following is helpful (and more importantly, correct).

#to_s is for providing a String representation when the caller
explicitly wants a string, e.g. for rendering purposes. For example,
Integer#to_s gives you a nice string representation of an integer,
which is pretty straightforward.

#to_str is for providing a String version when the caller
implicity wants a string, e.g. parameter passing. The motivation
here is typically for the class to fit in with the standard Ruby
classes. For example, the Pathname class (in stdlib) represents a
path to a file and has all sorts of funky path manipulation
capabilities. But since a path is essentially a String it makes
sense to provide Pathname#to_str so the following lines work:

File.open(pathname)
message = "Can’t find directory: " + pathname

Naturally, Pathname will also provide #to_s, and it will probably be
the same as #to_str.

However, Integer does not provide #to_str, because despite there being
a String representation of an integer, there is no String version
of an integer. If Integer#to_str were provided, then the following
would “work”:

“1” + 7 # “17” (yuck!)

And if you really want Perl, implement String#to_int so you can do

1 + “7” # 8 (YUCK!!!)

A relevant point should be made here about #to_s. It provides a
string representation of an object. There is no such thing as the
string representation of an object. Even the humble integer, whose
string rep is pretty damn obvious, is up for discussion. Do we want

-14.to_s # “-14”

or

-14.to_s # “(14)”

or even

-14.to_s # “(14)

?

Because of these different demands in different contexts, class
authors should be mindful of providing a #to_s implementation that is
not “obvious” and clearly desirable in a majority of cases.

I remember redefining #to_s at an object level, not a class level,
because its output was too long. It was conceptually correct in what
it was trying to provide, but for my purposes (unit testing) it was
simply too long.

REXML could do with some work on its #to_s methods. Take a large
XML document, select a (small) node within it and call #to_s, and go
make yourself a coffee while it prints reams of stuff to the screen :slight_smile:

Cheers,
Gavin

Does [ruby-talk:96552] help you? “to_str” should always be part of
String method set.

						matz.
···

In message “Difference between to_s and to_str” on 04/04/05, Gavin Sinclair gsinclair@soyabean.com.au writes:

There has been some discussion on this topic in the thread “deciding
between ruby and python”. It was centered around how far #join
should go in getting what it wants (a String) from an object. I
detected some misunderstanding at the intention of #to_s and #to_str,
so I hope the following is helpful (and more importantly, correct).

I think the problem with #join is that people disagree on whether it should
be a string representation or version.

Is #join a method that takes an array of objects that can be represented
as strings, or does it take an array of (implicit) strings (as you said that
#to_str is for implicit argument passing situations).

I agree with you.

  1. It’s more widely useful to use #to_s. Otherwise we can’t even do simple
    things like join arrays of integers by default.
  2. I don’t think you’ll catch any meaningful bugs with a failure on #to_str.
    At most, it will alert you that you need to define #to_str. :slight_smile:

However, not everybody may agree with such points.

  • Dan

P.S. For what it’s worth, I also agree with your statement earlier that #to_s
shouldn’t really be used for debugging, and that #inspect and #p are the
appropriate methods to use in that situation.

In article 1081126484.726652.9271.nullmailer@picachu.netlab.jp,
matz@ruby-lang.org (Yukihiro Matsumoto) writes:

Does [ruby-talk:96552] help you? “to_str” should always be part of
String method set.

Always? Pathname shouldn’t have to_str?

I agree that to_str is too powerful for Pathname because Gavin’s 2nd
example

message = "Can’t find directory: " + pathname

is not intended to work.

So I’m glad to see a conversion method dedicated only for a pathname.

···


Tanaka Akira

I must admit I’m a little confused by http://ruby-talk.org/blade/96552

Can I ask: what do you think of Pathname#to_str? Is it appropriate
in your opinion?

Cheers,
Gavin

···

On Monday, April 5, 2004, 10:54:42 AM, Yukihiro wrote:

In message “Difference between to_s and to_str” > on 04/04/05, Gavin Sinclair gsinclair@soyabean.com.au writes:

There has been some discussion on this topic in the thread “deciding
between ruby and python”. It was centered around how far #join
should go in getting what it wants (a String) from an object. I
detected some misunderstanding at the intention of #to_s and #to_str,
so I hope the following is helpful (and more importantly, correct).

Does [ruby-talk:96552] help you? “to_str” should always be part of
String method set.

In article 1081126484.726652.9271.nullmailer@picachu.netlab.jp,
matz@ruby-lang.org (Yukihiro Matsumoto) writes:

Does [ruby-talk:96552] help you? “to_str” should always be part of
String method set.

Always? Pathname shouldn’t have to_str?

I agree that to_str is too powerful for Pathname because Gavin’s 2nd
example

message = "Can’t find directory: " + pathname

is not intended to work.

I see nothing at all wrong with that line of code. It produces
exactly the result I expect, and with no nasty side effects.

What don’t you like about it?

So I’m glad to see a conversion method dedicated only for a pathname.

I’m not sure what you mean here.

Cheers,
Gavin

···

On Monday, April 5, 2004, 1:32:51 PM, Tanaka wrote:

Hi,

···

In message “Re: Difference between to_s and to_str” on 04/04/05, Tanaka Akira akr@m17n.org writes:

Does [ruby-talk:96552] help you? “to_str” should always be part of
String method set.

Always? Pathname shouldn’t have to_str?

I think so, when we can prepare other work around like “to_open” as in
RCR#233.

						matz.