Confused about to_s in Ruby / irb

I wish to control the default display of my objects, and thought to_s
would be the right hook. But ruby (at least irb) seems to use my to_s
only if the class has no instance variables. Am I doing something
wrong?

What other display-related hooks are there?

Thanks

class A
def to_s
“an A”
end
end
nil

A.new
an A # uses to_s

class B
def initialize(x)
@x = x
end
def to_s
“a B”
end
end
nil

B.new (5)
#<B:0x2a51b98 @x=5> # ignores to_s

Actually, irb uses “inspect” in this case.

Gennady.

···

----- Original Message -----
From: “you CAN teach an old dog …” itsme213@hotmail.com
Newsgroups: comp.lang.ruby
To: “ruby-talk ML” ruby-talk@ruby-lang.org
Sent: Thursday, June 12, 2003 4:26 PM
Subject: Confused about to_s in Ruby / irb

I wish to control the default display of my objects, and thought to_s
would be the right hook. But ruby (at least irb) seems to use my to_s
only if the class has no instance variables. Am I doing something
wrong?

What other display-related hooks are there?

Thanks

class A
def to_s
“an A”
end
end
nil

A.new
an A # uses to_s

class B
def initialize(x)
@x = x
end
def to_s
“a B”
end
end
nil

B.new (5)
#<B:0x2a51b98 @x=5> # ignores to_s

I wish to control the default display of my objects, and thought to_s
would be the right hook. But ruby (at least irb) seems to use my to_s
only if the class has no instance variables. Am I doing something
wrong?

What other display-related hooks are there?

I guess you know about p and puts, right?
puts obj
will call obj.to_s, but
p obj
will call obj.inspect instead.

I guess irb is doing the equivalent of a p.

There is also to_str, but the difference between
it and to_s is a little subtle. The to_s method
is for conversion – pretty much anything can be
converted to a string. The to_str method is used
when an objects wants to “masquerade” as a string.
One common difference is that the latter will
typically preserve all information, whereas the
former may only present enough to render the object
in a printable form. (At least I think I’ve seen
that distinction somewhere.)

Hal

···

----- Original Message -----
From: “you CAN teach an old dog …” itsme213@hotmail.com
Newsgroups: comp.lang.ruby
To: “ruby-talk ML” ruby-talk@ruby-lang.org
Sent: Thursday, June 12, 2003 6:26 PM
Subject: Confused about to_s in Ruby / irb

irb just shows what the input expression returns. The things you see
after each line are just string representations of what Ruby would
return internally if run in a program.

In ‘A’, your object only contains a method, so Ruby just returns the
result of invoking the method. I think the reason for this is that that
is all you asked the class to do.

In ‘B’, your object contains data values when initialized, so Ruby
returns the object (irb represents this by showing the result of [the
object].inspect). In a program the object would be available to be used
for further purposes (although you will likely want or need (if you’re
not chaining a bunch of methods) to assign it to a variable so that you
can reference it subsequently in your program.

To display the result of the to_s method in ‘B’ you would need to call
it:

B.new(5).to_s

If you assign a new object to a variable, you can always show the name
of the class by writing:

b = B.new(5)
puts b.class

I’m sure there are nuances I’m missing, but the above is my
understanding so far of what’s going on with irb and to_s.

···

On Thursday, June 12, 2003, at 07:26 PM, you CAN teach an old dog … wrote:

I wish to control the default display of my objects, and thought to_s
would be the right hook. But ruby (at least irb) seems to use my to_s
only if the class has no instance variables. Am I doing something
wrong?

What other display-related hooks are there?

Thanks

class A
def to_s
“an A”
end
end
nil

A.new
an A # uses to_s

class B
def initialize(x)
@x = x
end
def to_s
“a B”
end
end
nil

B.new (5)
#<B:0x2a51b98 @x=5> # ignores to_s

“Hal E. Fulton” hal9000@hypermetrics.com wrote in message

The to_str method is used when an objects wants to “masquerade”
as a string.

Meaning ?

One common difference is that the latter will
typically preserve all information, whereas the
former may only present enough to render the object
in a printable form. (At least I think I’ve seen
that distinction somewhere.)

Forgive me for being dense. Can you please explain this more ?
Maybe with an example ? All I have is a reference from PickAxe:

···

C:> ri to_str
This is a test ‘ri’. Please report errors and omissions
on http://www.rubygarden.org/ruby?RIOnePointEight

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

TIA,
–shanko

“Hal E. Fulton” hal9000@hypermetrics.com wrote > I guess you know
about p and puts, right?

puts obj
will call obj.to_s, but
p obj
will call obj.inspect instead.

Sounds reasonable, but it does not explain the behavior below. It
seems (p x) calls x.inspect if it is defined; otherwise it calls
x.to_s

class None; end
==> nil
p None.new
==> #None:0x2ac6110
puts None.new
==> #None:0x2ac46a0

class To_S; def to_s; "to_s "; end; end
==> nil
p To_S.new # how come?
==> to_s
puts To_S.new
==> to_s

class Inspect; def inspect; "inspect "; end; end
==> nil
p Inspect.new
==> inspect
puts Inspect.new
==> #Inspect:0x2ad97a8

class Both
def to_s; "Both: to_s "; end
def inspect; "Both: inspect "; end
end
==>nil

p Both.new
==> Both: inspect
puts Both.new
==> Both: to_s

“Hal E. Fulton” hal9000@hypermetrics.com wrote in message

The to_str method is used when an objects wants to “masquerade”
as a string.

Meaning ?

One common difference is that the latter will
typically preserve all information, whereas the
former may only present enough to render the object
in a printable form. (At least I think I’ve seen
that distinction somewhere.)

Forgive me for being dense. Can you please explain this more ?
Maybe with an example ? All I have is a reference from PickAxe:

You’re not dense. I still find it highly non-obvious.

All I know about this I learned from Dave Thomas.

I think I can get away with quoting this much of The
Ruby Way
, chapter 5. See below. Just don’t tell the
l-a-w-y-e-r-s.

Cheers,
Hal

···

----- Original Message -----
From: “Shashank Date” sdate@everestkc.net
Newsgroups: comp.lang.ruby
To: “ruby-talk ML” ruby-talk@ruby-lang.org
Sent: Thursday, June 12, 2003 10:48 PM
Subject: Re: Confused about to_s in Ruby / irb

========================================================

Sometimes an object comes in exactly the right form at the right time, but
sometimes we need to convert it to something else or pretend it’s something
it isn’t. A good example is the well-known to_s method.

Every object can be converted in some fashion to a string representation.
But not every object can successfully masquerade as a string. That in
essence is the difference between the to_s and to_str methods. Let’s
elaborate on that.

Methods such as puts and contexts such as #{…} interpolation in strings
expect to receive a String as a parameter. If they do not, they ask the
object they did receive to convert itself to a String by sending it a to_s
message. This is where you get to specify how your object will appear when
displayed; simply implement a to_s method in your class that returns an
appropriate String.

class Pet

  def initialize(name)
    @name = name
  end

  # ...

  def to_s
    "Pet: #@name"
  end

end

Other methods (such as the String concatenation operator +) are more picky;
they expect you to pass in something that is really pretty close to a
String. In this case, Matz decided not to have the interpreter call to_s to
convert non-string arguments, as he felt this would lead to too many errors.
Instead, the interpreter invokes a stricter method, to_str. Of the built-in
classes, only String and Exception implement to_str, and only String,
Regexp, and Marshal call it. Typically when you see the runtime error
TypeError: Failed to convert xyz into String, you know that the interpreter
tried to invoke to_str and failed.

You can implement to_str yourself. For example, you might want to allow
numbers to be concatenated to strings:

class Numeric

def to_str
  to_s
end

end

label = "Number " + 9 # “Number 9”

A class is an object. As such it gets a minimum collection of methods.
So when you create the class with

class To_S; def to_s; "to_s "; end; end

the class To_S has the following class methods, which can be viewed by
calling

To_S.methods

[“superclass”, “allocate”, “new”, “public_class_method”,
“public_instance_methods”, “private_method_defined?”, “<=>”,
“class_eval”, “constants”, “==”, “instance_methods”, “===”,
“public_method_defined?”, “module_eval”, “private_instance_methods”,
“included_modules”, “to_s”, “>=”, “<”, “<=”, “method_defined?”,
“const_set”, “ancestors”, “dup”, “>”, “private_class_method”,
“protected_instance_methods”, “include?”, “instance_method”,
“protected_method_defined?”, “class_variables”, “const_defined?”,
“const_get”, “name”, “clone”, “method”, “untaint”, “kind_of?”, “type”,
“instance_variable_get”, “inspect”, “display”, “frozen?”, “taint”,
“send”, “private_methods”, “id”, “=~”, “to_a”, “eql?”, “hash”,
“singleton_methods”, “nil?”, “freeze”, “is_a?”, “class”,
“instance_variable_set”, “methods”, “send”, “instance_eval”,
“extend”, “object_id”, “instance_variables”, “instance_of?”,
“copy_object”, “id”, “protected_methods”, “equal?”, “respond_to?”,
“tainted?”, “public_methods”]

If you call

To_S.new.methods

you get the following instance methods:

[“to_s”, “method”, “untaint”, “kind_of?”, “type”,
“instance_variable_get”, “inspect”, “display”, “frozen?”, “taint”,
“send”, “private_methods”, “id”, “=~”, “to_a”, “eql?”, “dup”,
“hash”, “singleton_methods”, “nil?”, “freeze”, “is_a?”, “class”,
“instance_variable_set”, “methods”, “send”, “instance_eval”,
“extend”, “object_id”, “instance_variables”, “instance_of?”,
“copy_object”, “id”, “protected_methods”, “equal?”, “respond_to?”,
“clone”, “tainted?”, “==”, “public_methods”, “===”]

Regards,

Mark Wilson

···

On Friday, June 13, 2003, at 02:50 AM, you CAN teach an old dog … wrote:

[snip]

class To_S; def to_s; "to_s "; end; end
==> nil
p To_S.new # how come?
==> to_s
puts To_S.new
==> to_s

[snip]

“Hal E. Fulton” hal9000@hypermetrics.com wrote > I guess you know
about p and puts, right?

puts obj
will call obj.to_s, but
p obj
will call obj.inspect instead.

Sounds reasonable, but it does not explain the behavior below. It
seems (p x) calls x.inspect if it is defined; otherwise it calls
x.to_s

That’s because

static VALUE
rb_obj_inspect(obj)
VALUE obj;
{
if (TYPE(obj) == T_OBJECT
&& ROBJECT(obj)->iv_tbl
&& ROBJECT(obj)->iv_tbl->num_entries > 0) {


}
return rb_funcall(obj, rb_intern(“to_s”), 0, 0);
}

So in fact #inspect returns #to_s() when the object has got no instance
vars:

class A; def to_s; “A#to_s” end end
=> nil
a = A.new
=> A#to_s
a.instance_eval { @a = 1 }
=> 1
a
=> #<A:0x401d0f20 @a=1>

···

On Fri, Jun 13, 2003 at 03:50:31PM +0900, you CAN teach an old dog … wrote:


_ _

__ __ | | ___ _ __ ___ __ _ _ __
'_ \ / | __/ __| '_ _ \ / ` | ’ \
) | (| | |
__ \ | | | | | (| | | | |
.__/ _,
|_|/| || ||_,|| |_|
Running Debian GNU/Linux Sid (unstable)
batsman dot geo at yahoo dot com

LILO, you’ve got me on my knees!
– David Black, dblack@pilot.njin.net, with apologies to Derek and the
Dominos, and Werner Almsberger