Forum: Ruby print uses to_s but puts does not

A71b4cc3b9acbe85c56181f281634907?d=identicon&s=25 Bry So (bso)
on 2016-09-15 22:51
I want to create a MyArray that prints the array with space delimiters.
.print works but .puts doesn't.  Why?  Thanks

class MyArray < Array
    def initialize(x)

    def to_s
        "DEBUG " + join(' ')

irb(main):057:0> load "MyArray.rb"
=> true
irb(main):058:0> a =[1, 2, 3, 4])
=> [1, 2, 3, 4]
irb(main):059:0> puts a
=> nil
irb(main):060:0> print a
DEBUG 1 2 3 4=> nil

Version Info

>>>ruby --version
ruby 2.0.0p481 (2014-05-08 revision 45883) [universal.x86_64-darwin14]
>>>irb --version
irb 0.9.6(09/06/30)
6c7fb11d4f3fa354a51a3ea0375d895f?d=identicon&s=25 Joe Gain (timeout)
on 2016-09-16 07:39
But, what about:

class A < Array

a = A([1, 2, 3])

puts a #=> 1, ...
0fa73332c8e4a3b06ea439fd3f034322?d=identicon&s=25 Ronald Fischer (rovf)
on 2016-09-16 07:53
It is because

    puts x

is equivalent to

6c7fb11d4f3fa354a51a3ea0375d895f?d=identicon&s=25 Joe Gain (timeout)
on 2016-09-16 08:11
Yes, this was a good question. I didn't realise this until I did some
more testing and than I was confused as well.

Here's a stackoverflow question which explains how to use to_s with
subclassed Arrays:

I wonder why it's like this? From an OO point of view it's not a nice
solution, because puts needs to know what type of class the argument is.
There must be a pragmatic reason?

The reason's in the documentation:

It seems something like tradition, so that puts acts like C's printf or
Javascript console.log, it wants to work on something like *args.
0fa73332c8e4a3b06ea439fd3f034322?d=identicon&s=25 Ronald Fischer (rovf)
on 2016-09-16 08:23
This has nothing to do with OOP. The "basic method" for outputting
something is IO#print. You can stick with this, if you want.

To make things easier to use in many convenient cases, Ruby also has
IO#puts, Kernel#print, Kernel#p, Kernel#pp, and several others. You can
use them, if they fit you. You can create new ones, if you are not
satisfied with them. For instance, if you have the habit to add to most
of your classes a method named :myFancyPrinting, you could add a method
of this name to, say, Kernel, and define it to invoke :myFancyPrinting
on the argument (if it is defined) and revert to, say, Kernel#puts if it

In your case, you are picking from the list two arbitrary methods -
Kernel#print and Kernel#puts - and wonder, why they behave differently.
Well, why should they behave the same? They serve a slightly different
A71b4cc3b9acbe85c56181f281634907?d=identicon&s=25 Bry So (bso)
on 2016-09-16 17:15
Ronald Fischer wrote in post #1185017:
> It is because
>     puts x
> is equivalent to
>     print(x.to_s+"\n")

No they are not.

    irb(main):004:0> x =[1, 2, 3])
    => [1, 2, 3]

    irb(main):005:0> puts x

    irb(main):006:0> print(x.to_s+"\n")
    DEBUG 1 2 3

How are these equivalent?

Joe, your doc link is useful.  It makes "common sense" although Ronald's
equivalence theory is what I had in mind initially.  I'll rephrase my
understanding of a new equivalence theory:

    puts x

is probably equivalent to

    if x.is_a? Array then
        x.each { |i| puts i.to_s }

I thank you both for taking the time to respond.  It's this type of
exchange and investigation that gives deep understanding.
Please log in before posting. Registration is free and takes only a minute.
Existing account

NEW: Do you have a Google/GoogleMail, Yahoo or Facebook account? No registration required!
Log in with Google account | Log in with Yahoo account | Log in with Facebook account
No account? Register here.