283

For example in this line of code I wrote, print and puts produce different results.

1.upto(1000).each { |i| print i if i % 2 == 0 }
Mark Amery
  • 143,130
  • 81
  • 406
  • 459
  • 1
    See also https://stackoverflow.com/questions/612258/whats-the-difference-between-rubys-puts-and-write-methods, http://stackoverflow.com/questions/1255324/p-vs-puts-in-ruby, and http://stackoverflow.com/questions/4415834/print-function-in-ruby – Phrogz Feb 16 '11 at 16:09

6 Answers6

403

puts adds a new line to the end of each argument if there is not one already.

print does not add a new line.


For example:

puts [[1,2,3], [4,5,nil]] Would return:

1
2
3
4
5

Whereas print [[1,2,3], [4,5,nil]] would return:

[[1,2,3], [4,5,nil]]
Notice how puts does not output the nil value whereas print does.
Chay Huan
  • 123
  • 1
  • 10
mikewilliamson
  • 24,303
  • 17
  • 59
  • 90
62

A big difference is if you are displaying arrays. Especially ones with NIL. For example:

print [nil, 1, 2]

gives

[nil, 1, 2]

but

puts [nil, 1, 2]

gives

1
2

Note, no appearing nil item (just a blank line) and each item on a different line.

Micka
  • 1,648
  • 1
  • 19
  • 34
MBentley
  • 995
  • 10
  • 16
  • 1
    I noticed this today, which brought me here. I'd love to know the thinking on that. It seems like a special case for puts to handle arrays like that. Wondering what the rationale was... Is it just to be analogous to other languages? – Dan Barron Jul 10 '13 at 13:49
  • It makes sense since puts will output with a new line, so you can think of it as iterating on the array and calling puts on each line... it is odd, however, that it doesn't output `nil` – Muers May 13 '14 at 18:40
42

print outputs each argument, followed by $,, to $stdout, followed by $\. It is equivalent to args.join($,) + $\

puts sets both $, and $\ to "\n" and then does the same thing as print. The key difference being that each argument is a new line with puts.

You can require 'english' to access those global variables with user-friendly names.

wersimmon
  • 2,809
  • 3
  • 22
  • 35
18

The API docs give some good hints:

print() → nil

print(obj, ...) → nil

Writes the given object(s) to ios. Returns nil.

The stream must be opened for writing. Each given object that isn't a string will be converted by calling its to_s method. When called without arguments, prints the contents of $_.

If the output field separator ($,) is not nil, it is inserted between objects. If the output record separator ($\) is not nil, it is appended to the output.

...

puts(obj, ...) → nil

Writes the given object(s) to ios. Writes a newline after any that do not already end with a newline sequence. Returns nil.

The stream must be opened for writing. If called with an array argument, writes each element on a new line. Each given object that isn't a string or array will be converted by calling its to_s method. If called without arguments, outputs a single newline.

Experimenting a little with the points given above, the differences seem to be:

  • Called with multiple arguments, print separates them by the 'output field separator' $, (which defaults to nothing) while puts separates them by newlines. puts also puts a newline after the final argument, while print does not.

    2.1.3 :001 > print 'hello', 'world'
    helloworld => nil 
    2.1.3 :002 > puts 'hello', 'world'
    hello
    world
     => nil
    2.1.3 :003 > $, = 'fanodd'
     => "fanodd" 
    2.1.3 :004 > print 'hello', 'world'
    hellofanoddworld => nil 
    2.1.3 :005 > puts 'hello', 'world'
    hello
    world
     => nil
  • puts automatically unpacks arrays, while print does not:

    2.1.3 :001 > print [1, [2, 3]], [4]
    [1, [2, 3]][4] => nil 
    2.1.3 :002 > puts [1, [2, 3]], [4]
    1
    2
    3
    4
     => nil
  • print with no arguments prints $_ (the last thing read by gets), while puts prints a newline:

    2.1.3 :001 > gets
    hello world
     => "hello world\n" 
    2.1.3 :002 > puts
    
     => nil 
    2.1.3 :003 > print
    hello world
     => nil
  • print writes the output record separator $\ after whatever it prints, while puts ignores this variable:

    mark@lunchbox:~$ irb
    2.1.3 :001 > $\ = 'MOOOOOOO!'
     => "MOOOOOOO!" 
    2.1.3 :002 > puts "Oink! Baa! Cluck! "
    Oink! Baa! Cluck! 
     => nil 
    2.1.3 :003 > print "Oink! Baa! Cluck! "
    Oink! Baa! Cluck! MOOOOOOO! => nil
Mark Amery
  • 143,130
  • 81
  • 406
  • 459
4

puts call the to_s of each argument and adds a new line to each string, if it does not end with new line. print just output each argument by calling their to_s.

for example: puts "one two": one two

{new line}

puts "one two\n": one two

{new line} #puts will not add a new line to the result, since the string ends with a new line

print "one two": one two

print "one two\n": one two

{new line}

And there is another way to output: p

For each object, directly writes obj.inspect followed by a newline to the program’s standard output.

It is helpful to output debugging message. p "aa\n\t": aa\n\t

ryan
  • 847
  • 1
  • 10
  • 18
-1

If you would like to output array within string using puts, you will get the same result as if you were using print:

puts "#{[0, 1, nil]}":
[0, 1, nil]

But if not withing a quoted string then yes. The only difference is between new line when we use puts.

Michael
  • 2,631
  • 2
  • 24
  • 40
fog1985
  • 155
  • 1
  • 7
  • 1
    -1 for two reasons. Firstly, a lack of clarity: I don't understand what the initial "But..." here intends for this to follow on from, nor do I understand what the "yes" in the final paragraph is replying to. Secondly, for a lack of correctness: you say that using `printf` instead of `puts` in your example code will give the same result, but in fact it doesn't. The `puts` variant adds a newline at the end while the `printf` one doesn't, just like the case where there's no array interpolated into the string. (Necessarily so, since the interpolation happens when evaluating the string literal.) – Mark Amery Apr 22 '19 at 12:17
  • 1
    Aha! After reading other answers, I think I understand - you intended this to be a reply to https://stackoverflow.com/a/14534145/1709587? In any case, it doesn't really stand a an answer on its own. – Mark Amery Apr 22 '19 at 12:19