Y a-t-il une différence entre p
et puts
en Ruby?
Y a-t-il une différence entre p
et puts
en Ruby?
Réponses:
p foo
imprime foo.inspect
suivi d'une nouvelle ligne, c'est-à-dire qu'il imprime la valeur de inspect
au 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
).
p
renvoie également la valeur de l'objet, alors puts
que non. 1.9.3p125 :002 > (p "foo").class "foo" => String 1.9.3p125 :003 > (puts "foo").class foo => NilClass
to_s
est 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 p
retourne 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).
Il est également important de noter que puts
"réagit" à une classe qui l'a to_s
définie, p
ne 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' .inspect
appel, mais n'est pas évident en pratique.
p foo
est le même que puts foo.inspect
puts
revient nil
, au lieu de foo
le faire p
.
puts foo.inspect; foo
(-> {p "Hello World"}.call) == (-> {puts "Hello World".inspect}.call )
. Beaucoup de votes positifs n'en font PAS une bonne réponse!
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
>> ******
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(obj) → obj click to toggle source
p(obj1, obj2, ...) → [obj, ...]
p() → nil
Pour chaque objet, écrit directementobj.inspect
suivi 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
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 )
(->{p "Hello World"}.call) == (-> {puts "Hello World".inspect}.call )
Cela peut illustrer l'une des principales différences qui est celle qui p
renvoie la valeur de ce qui lui est transmis, où en tant que puts
retour 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 puts
est 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)