p vs ставить у Ruby


Відповіді:


334

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


7
Так, p (і ставить) обидва в модулі 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
Велике резюме, яке надав Гарет Різ у своєму дописі "Рубі п проти ставить проти друку" .
alexanderjsingleton

Якесь таке відчуття, як це залишає у мене кролячу дірку питань. Що перевіряти? Що до_с? Чому я хочу перевірити друкований текст замість змінної? Що є більш стандартним для світу програмування, через вашу згадку про налагодження, p або put? Чи слід замінити всі "p" на "put" після завершення налагодження ?? Я бачу, що в коментарі вище, що p повертає об'єкт, що є величезною різницею. Я не впевнений, чи є ця відповідь повною, якщо вона лише згадує про невелику різницю, що призведе до великих запитань, які все-таки відповідають на оригінальне запитання.

1
@AaronLoften to_s- це стандартний метод-стринг у Ruby. inspect. як я вже говорив, це альтернативний строковому методу, який дає результат більш підходящий для налагодження. Після завершення налагодження, очевидно, слід видалити ваші заяви про налагодження (або для більш серйозних проектів ви, мабуть, повинні використовувати рамку реєстрації та взагалі не використовувати p або put для налагодження). Той факт, що pповертає об’єкт, здається неактуальним у більшості ситуацій (і я вважаю, що я дав цю відповідь, перш ніж це було так). Різниця у виході - головна відмінність (і раніше була єдиною).
sepp2k

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дзвінка, але це не очевидно на практиці.


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

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

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

0

Ці 2 рівні:

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

( Inspect дає більш буквальний вигляд об'єкта порівняно з методом to_s )


вони здаються рівними, але вони НЕ. Спробуйте:(->{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)
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.