Forum: Ruby print uses to_s but puts does not

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
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)
        super
    end

    def to_s
        "DEBUG " + join(' ')
    end
end

irb(main):057:0> load "MyArray.rb"
=> true
irb(main):058:0> a = MyArray.new([1, 2, 3, 4])
=> [1, 2, 3, 4]
irb(main):059:0> puts a
1
2
3
4
=> 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
end

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

    print(x.to_s+"\n")
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:
http://stackoverflow.com/questions/11463873/ruby-o...

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:
http://ruby-doc.org/core-2.2.2/IO.html#method-i-puts

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
isn't.

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
purpose.
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 = MyArray.new([1, 2, 3])
    => [1, 2, 3]

    irb(main):005:0> puts x
    1
    2
    3

    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 }
    else
        print(x.to_s+"\n")
    end

I thank you both for taking the time to respond.  It's this type of
exchange and investigation that gives deep understanding.
This topic is locked and can not be replied to.