Есть ли разница между p
и puts
в Ruby?
Есть ли разница между p
и puts
в Ruby?
Ответы:
p foo
печатает foo.inspect
после новой строки, то есть печатает значение inspect
вместо to_s
, которое больше подходит для отладки (потому что вы можете, например, определить разницу между 1
, "1"
и "2\b1"
, что вы не можете при печати без inspect
).
p
также возвращает значение объекта, а puts
нет. 1.9.3p125 :002 > (p "foo").class "foo" => String 1.9.3p125 :003 > (puts "foo").class foo => NilClass
to_s
- это стандартный метод для обработки строк в Ruby. inspect
, Как я уже сказал, это альтернативный строковый метод, который производит вывод, более подходящий для отладки. После завершения отладки вы, очевидно, должны удалить свои операторы отладки (или для более серьезных проектов вы, вероятно, должны использовать каркас ведения журналов и вообще не использовать p или put для отладки). Тот факт, что p
объект возвращается, кажется, не имеет значения в большинстве ситуаций (и я полагаю, что дал этот ответ раньше, чем это было так). Разница в выходных данных является основным (и раньше была единственной).
Также важно отметить, что puts
«реагирует» на класс, который to_s
определил, p
не делает. Например:
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>
Это следует непосредственно из .inspect
звонка, но не очевидно на практике.
p foo
такой же как puts foo.inspect
puts
возвращает nil
, foo
а не как делает p
.
puts foo.inspect; foo
(-> {p "Hello World"}.call) == (-> {puts "Hello World".inspect}.call )
. Много голосов не делает это хорошим ответом!
В дополнение к ответам выше, есть небольшая разница в выводе консоли, а именно: наличие / отсутствие кавычек / кавычек, - которые могут быть полезны:
p "+++++"
>> "+++++"
puts "====="
>> =====
Я считаю это полезным, если вы хотите сделать простой индикатор выполнения, используя их близкий родственник, напечатайте :
array = [lots of objects to be processed]
array.size
>> 20
Это дает индикатор прогресса 100%:
puts "*" * array.size
>> ********************
И это добавляет добавочный * на каждую итерацию:
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
>> ******
Из документа ruby-2.4.1
puts(obj, ...) → nil
Записывает данный объект (ы) в ios. Записывает новую строку после любой, которая еще не заканчивается последовательностью новой строки. Возвращает ноль .
Поток должен быть открыт для записи. При вызове с аргументом массива записывает каждый элемент в новую строку. Каждый данный объект, который не является строкой или массивом, будет преобразован путем вызова его
to_s
метода. Если вызывается без аргументов, выводится одна новая строка.
давайте попробуем это на 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(obj) → obj click to toggle source
p(obj1, obj2, ...) → [obj, ...]
p() → nil
Для каждого объекта непосредственно записывается сobj.inspect
последующим переводом строки в стандартный вывод программы.
в ирб
# 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
Эти 2 равны:
p "Hello World"
puts "Hello World".inspect
( inspect дает более буквальное представление об объекте по сравнению с методом to_s )
(->{p "Hello World"}.call) == (-> {puts "Hello World".inspect}.call )
Это может проиллюстрировать одно из ключевых отличий, которое заключается в том, что p
возвращает значение того, что ему передано, а где puts
возвращается 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']
Тесты показывают puts
медленнее
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)