296

Is there any difference between p and puts in Ruby?

Undo
  • 25,519
  • 37
  • 106
  • 129
collimarco
  • 34,231
  • 36
  • 108
  • 142

8 Answers8

356

p foo prints foo.inspect followed by a newline, i.e. it prints the value of inspect instead of to_s, which is more suitable for debugging (because you can e.g. tell the difference between 1, "1" and "2\b1", which you can't when printing without inspect).

M. Glatki
  • 777
  • 6
  • 18
sepp2k
  • 363,768
  • 54
  • 674
  • 675
  • 8
    Yep, p (and puts) are both in the Kernel module so you can see the details here: http://www.ruby-doc.org/core/classes/Kernel.html#M005961 – mikej Aug 10 '09 at 14:54
  • 22
    Note that `p` also returns the value of the object, while `puts` does not. `1.9.3p125 :002 > (p "foo").class "foo" => String 1.9.3p125 :003 > (puts "foo").class foo => NilClass` – Darren Cheng Nov 21 '12 at 22:15
  • 3
    Great summary provided by Gareth Rees in his post entitled ["Ruby p vs puts vs print"](http://www.garethrees.co.uk/2013/05/04/p-vs-puts-vs-print-in-ruby/). – alexanderjsingleton Feb 26 '16 at 04:24
  • Kinda feel like this leaves me with a rabbit hole of questions. Whats inspect? Whats to_s? Why do I want to inspect printed text instead of a variable? Which is more standard for the world of programming, due to your mention of debugging, p or puts? Should all "p" be replaced with "puts" upon completion of debugging?? I see, in an above comment, that p returns an object, which is a huge difference. Im not sure if this answer is complete if it only mentions a small difference that will lead to bigger questions that still kind of answer the original question. –  Oct 04 '16 at 20:44
  • 1
    @AaronLoften `to_s` is the standard to-string method in Ruby. `inspect`. as I said, is an alternative to-string method, which produces an output more suitable for debugging. Upon completion of debugging you should obviously remove your debugging statements (or for more serious projects you should probably use a logging framework and not use p or puts for debugging at all). The fact that `p` returns the object seems irrelevant in most situations (and I believe I gave this answer before this was the case). The difference in output is the main difference (and used to be the only one). – sepp2k Oct 04 '16 at 20:55
  • Unless `foo` is an array, then `puts` prints `to_s` for each element on a separate line rather than `foo.to_s`. – jonvw May 28 '20 at 05:55
55

It is also important to note that puts "reacts" to a class that has to_s defined, p does not. For example:

class T
   def initialize(i)
      @i = i
   end
   def to_s
      @i.to_s
   end
end

t = T.new 42
puts t   => 42
p t      => #<T:0xb7ecc8b0 @i=42>

This follows directly from the .inspect call, but is not obvious in practice.

Pierre-Adrien
  • 2,836
  • 29
  • 30
ezpz
  • 11,767
  • 6
  • 38
  • 39
40

p foo is the same as puts foo.inspect

August Lilleaas
  • 54,010
  • 13
  • 102
  • 111
5

From ruby-2.4.1 document

puts

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.

let's try it on irb

# always newline in the end 
>> puts # no arguments

=> nil # return nil and writes a newline
>> puts "sss\nsss\n" # newline in string
sss
sss
=> nil
>> puts "sss\nsss" # no newline in string
sss
sss
=> nil

# for multiple arguments and array
>> puts "a", "b"
a
b
=> nil
>> puts "a", "b", ["c", "d"]
a
b
c
d
=> nil

p

p(obj) → obj click to toggle source
p(obj1, obj2, ...) → [obj, ...] p() → nil
For each object, directly writes obj.inspect followed by a newline to the program’s standard output.

in irb

# no arguments
>> p
=> nil # return nil, writes nothing
# one arguments
>> p "sss\nsss\n" 
"sss\nsss\n"
=> "aaa\naaa\n"
# multiple arguments and array
>> p "a", "b"
"a"
"b"
=> ["a", "b"] # return a array
>> p "a", "b", ["c", "d"]
"a"
"b"
["c", "d"]
=> ["a", "b", ["c", "d"]] # return a nested array
Fangxing
  • 5,716
  • 2
  • 49
  • 53
3

In addition to the above answers, there is a subtle difference in console output - namely the presence/absence of inverted commas/quotation marks - that can be useful:

p "+++++"
>> "+++++"

puts "====="
>> =====

I find this useful if you want to make a simple progress bar, using the their close relative, print:

array = [lots of objects to be processed]
array.size
>> 20

This gives the 100% progress bar:

puts "*" * array.size
>> ********************

And this adds an incremental * on each iteration:

array.each do |obj|
   print "*"
   obj.some_long_executing_process
end

# This increments nicely to give the dev some indication of progress / time until completion
>> ******
Jonathan_W
  • 638
  • 9
  • 24
0

These 2 are equal:

p "Hello World"  
puts "Hello World".inspect

(inspect gives a more literal view of the object compared to to_s method)

apadana
  • 13,456
  • 15
  • 82
  • 98
0

This may illustrate one of the key differences which is that p returns the value of what is passed to it, where as puts returns nil.

def foo_puts
  arr = ['foo', 'bar']
  puts arr
end

def foo_p
  arr = ['foo', 'bar']
  p arr
end

a = foo_puts
=>nil
a
=>nil

b = foo_p
=>['foo', 'bar']
b
['foo', 'bar']

Benchmark shows puts is slower

require 'benchmark'
str = [*'a'..'z']
str = str*100
res = Benchmark.bm do |x|
  x.report(:a) { 10.times {p str} }
  x.report(:b) { 10.times {puts str} }
end
puts "#{"\n"*10}"
puts res

0.010000   0.000000   0.010000 (  0.047310)
0.140000   0.090000   0.230000 (  0.318393)
lacostenycoder
  • 10,623
  • 4
  • 31
  • 48
0

p method will print more extensive debuggable message, where puts will prettify message code.

e.g see below lines of code:

msg = "hey, Use \#{ to interpolate expressions"
puts msg #clean msg
p msg #shows \ with #

output will be

hey, Use #{ to interpolate expressions
"hey, Use \#{ to interpolate expressions"

see output pic for more clarity

Roberto Caboni
  • 7,252
  • 10
  • 25
  • 39