Есть ли разница между 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)