p vs puts in Ruby
RubyRuby 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"