Difference between to_s and to_str

G

Gavin Sinclair

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 # "<span class="negative-number">(14)</span>"

?

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 :)

Cheers,
Gavin
 
Y

Yukihiro Matsumoto

In message "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).

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

matz.
 
D

Dan Doel

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. :)

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.
 
T

Tanaka Akira

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.
 
G

Gavin Sinclair

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
 
G

Gavin Sinclair

In message "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).
Does [ruby-talk:96552] help you? "to_str" should always be part of
String method set.

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
 
Y

Yukihiro Matsumoto

Hi,

In message "Re: Difference between to_s and to_str"

|> 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.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,579
Members
45,053
Latest member
BrodieSola

Latest Threads

Top