p vs puts in Ruby

2019-01-03 12:16发布

问题:

Is there any difference between p and puts in Ruby?

回答1:

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



回答2:

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.



回答3:

p foo is the same as puts foo.inspect



回答4:

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


回答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


回答6:

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)



标签: