p vs met en rubis

270

Y a-t-il une différence entre pet putsen Ruby?

collimarco
la source

Réponses:

334

p fooimprime foo.inspectsuivi d'une nouvelle ligne, c'est-à-dire qu'il imprime la valeur de inspectau lieu de to_s, ce qui est plus approprié pour le débogage (parce que vous pouvez par exemple faire la différence entre 1, "1"et "2\b1", ce que vous ne pouvez pas lorsque vous imprimez sans inspect).

sepp2k
la source
7
Oui, p (et put) sont tous les deux dans le module du noyau, vous pouvez donc voir les détails ici: ruby-doc.org/core/classes/Kernel.html#M005961
mikej
17
Notez que prenvoie également la valeur de l'objet, alors putsque non. 1.9.3p125 :002 > (p "foo").class "foo" => String 1.9.3p125 :003 > (puts "foo").class foo => NilClass
Darren Cheng
2
Grand résumé fourni par Gareth Rees dans son article intitulé "Ruby p vs put vs print" .
alexanderjsingleton
J'ai l'impression que cela me laisse un trou de lapin de questions. Quoi inspecter? Quel est to_s? Pourquoi dois-je inspecter le texte imprimé au lieu d'une variable? Qu'est-ce qui est plus standard pour le monde de la programmation, en raison de votre mention de débogage, p ou put? Est-ce que tous les "p" doivent être remplacés par "met" à la fin du débogage ?? Je vois, dans un commentaire ci-dessus, que p retourne un objet, ce qui est une énorme différence. Je ne sais pas si cette réponse est complète si elle ne mentionne qu'une petite différence qui conduira à des questions plus importantes qui répondront toujours à la question d'origine.
1
@AaronLoften to_sest la méthode standard de chaîne dans Ruby. inspect. comme je l'ai dit, est une méthode alternative à la chaîne, qui produit une sortie plus adaptée au débogage. À la fin du débogage, vous devez évidemment supprimer vos instructions de débogage (ou pour des projets plus sérieux, vous devriez probablement utiliser un cadre de journalisation et ne pas utiliser du tout p ou put pour le débogage). Le fait que pretourne l'objet semble hors de propos dans la plupart des situations (et je crois avoir donné cette réponse avant que ce soit le cas). La différence de sortie est la principale différence (et était la seule).
sepp2k
54

Il est également important de noter que puts"réagit" à une classe qui l'a to_sdéfinie, pne le fait pas. Par exemple:

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>

Cela découle directement de l' .inspectappel, mais n'est pas évident en pratique.

ezpz
la source
37

p foo est le même que puts foo.inspect

August Lilleaas
la source
4
mais putsrevient nil, au lieu de foole faire p.
ribamar
10
C'est faux. C'est la même chose queputs foo.inspect; foo
Eric Duminil
Cela prouve que vous êtes réponse est incorrecte: (-> {p "Hello World"}.call) == (-> {puts "Hello World".inspect}.call ) . Beaucoup de votes positifs n'en font PAS une bonne réponse!
lacostenycoder
3

En plus des réponses ci-dessus, il existe une différence subtile dans la sortie de la console - à savoir la présence / absence de virgules / guillemets inversés - qui peut être utile:

p "+++++"
>> "+++++"

puts "====="
>> =====

Je trouve cela utile si vous voulez faire une barre de progression simple, en utilisant leur proche parent, imprimez :

array = [lots of objects to be processed]
array.size
>> 20

Cela donne la barre de progression à 100%:

puts "*" * array.size
>> ********************

Et cela ajoute un incrémental * à chaque itération:

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
la source
2

Du document ruby-2.4.1

met

puts(obj, ...) → nil

Écrit le ou les objets donnés dans ios. Écrit une nouvelle ligne après une séquence qui ne se termine pas déjà par une séquence de nouvelle ligne. Renvoie nil .

Le flux doit être ouvert pour l'écriture. S'il est appelé avec un argument tableau , écrit chaque élément sur une nouvelle ligne. Chaque objet donné qui n'est pas une chaîne ou un tableau sera converti en appelant sa to_s méthode. S'il est appelé sans arguments, génère une seule nouvelle ligne.

essayons sur 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
Pour chaque objet, écrit directement obj.inspectsuivi d'un retour à la sortie standard du programme.

en 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
fangxing
la source
0

Ces 2 sont égaux:

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

( inspect donne une vue plus littérale de l'objet par rapport à la méthode to_s )

apadana
la source
ils semblent égaux, mais ils ne le sont PAS. Essayez-le:(->{p "Hello World"}.call) == (-> {puts "Hello World".inspect}.call )
lacostenycoder
0

Cela peut illustrer l'une des principales différences qui est celle qui prenvoie la valeur de ce qui lui est transmis, où en tant que putsretour 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']

L'indice de référence putsest plus lent

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
la source