p vs puts in Ruby

Ruby

Ruby Problem Overview


Is there any difference between p and puts in Ruby?

Ruby Solutions


Solution 1 - Ruby

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).

Solution 2 - Ruby

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.

Solution 3 - Ruby

p foo is the same as puts foo.inspect

Solution 4 - Ruby

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

Solution 5 - Ruby

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
>> ******

Solution 6 - Ruby

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)

Solution 7 - Ruby

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)

Solution 8 - Ruby

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

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestioncollimarcoView Question on Stackoverflow
Solution 1 - Rubysepp2kView Answer on Stackoverflow
Solution 2 - RubyezpzView Answer on Stackoverflow
Solution 3 - RubyAugust LilleaasView Answer on Stackoverflow
Solution 4 - RubyfangxingView Answer on Stackoverflow
Solution 5 - RubyJonathan_WView Answer on Stackoverflow
Solution 6 - RubyapadanaView Answer on Stackoverflow
Solution 7 - RubylacostenycoderView Answer on Stackoverflow
Solution 8 - RubyMohnish BhamraView Answer on Stackoverflow