р против ставит в руби

Ответы:

334

p fooпечатает foo.inspectпосле новой строки, то есть печатает значение inspectвместо to_s, которое больше подходит для отладки (потому что вы можете, например, определить разницу между 1, "1"и "2\b1", что вы не можете при печати без inspect).

sepp2k
источник
7
Да, p (и put) находятся в модуле Kernel, поэтому вы можете увидеть подробности здесь: ruby-doc.org/core/classes/Kernel.html#M005961
mikej
17
Обратите внимание, что pтакже возвращает значение объекта, а putsнет. 1.9.3p125 :002 > (p "foo").class "foo" => String 1.9.3p125 :003 > (puts "foo").class foo => NilClass
Даррен Ченг
2
Большое резюме, предоставленное Гаретом Рисом в его посте под названием "Ruby p vs put vs print" .
alexanderjsingleton
Что-то вроде того, что это оставляет меня с кроличьей норе вопросов. Что проверять? Что? Почему я хочу проверять печатный текст вместо переменной? Что является более стандартным для мира программирования из-за вашего упоминания об отладке, р или пут? Должны ли все "p" быть заменены на "put" после завершения отладки? В приведенном выше комментарии я вижу, что p возвращает объект, что является огромной разницей. Я не уверен, что этот ответ является полным, если в нем упоминается лишь небольшая разница, которая приведет к более крупным вопросам, которые все еще отчасти отвечают первоначальному вопросу.
1
@AaronLoften to_s- это стандартный метод для обработки строк в Ruby. inspect, Как я уже сказал, это альтернативный строковый метод, который производит вывод, более подходящий для отладки. После завершения отладки вы, очевидно, должны удалить свои операторы отладки (или для более серьезных проектов вы, вероятно, должны использовать каркас ведения журналов и вообще не использовать p или put для отладки). Тот факт, что pобъект возвращается, кажется, не имеет значения в большинстве ситуаций (и я полагаю, что дал этот ответ раньше, чем это было так). Разница в выходных данных является основным (и раньше была единственной).
сентября
54

Также важно отметить, что 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звонка, но не очевидно на практике.

EZPZ
источник
37

p foo такой же как puts foo.inspect

Август Лиллеас
источник
4
но putsвозвращает nil, fooа не как делает p.
Рибамар
10
Это неверно. Это так же, какputs foo.inspect; foo
Эрик Думинил
Это доказывает, что вы ответили неверно (-> {p "Hello World"}.call) == (-> {puts "Hello World".inspect}.call ) . Много голосов не делает это хорошим ответом!
lacostenycoder
3

В дополнение к ответам выше, есть небольшая разница в выводе консоли, а именно: наличие / отсутствие кавычек / кавычек, - которые могут быть полезны:

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
>> ******
Jonathan_W
источник
2

Из документа 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
Fangxing
источник
0

Эти 2 равны:

p "Hello World"  
puts "Hello World".inspect

( inspect дает более буквальное представление об объекте по сравнению с методом to_s )

Apadana
источник
они кажутся равными, но это не так. Попробуйте это:(->{p "Hello World"}.call) == (-> {puts "Hello World".inspect}.call )
lacostenycoder
0

Это может проиллюстрировать одно из ключевых отличий, которое заключается в том, что 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)
lacostenycoder
источник