¿Hay alguna diferencia entre p
y puts
en Ruby?
¿Hay alguna diferencia entre p
y puts
en Ruby?
Respuestas:
p foo
imprime foo.inspect
seguido de una nueva línea, es decir, imprime el valor de en inspect
lugar de to_s
, que es más adecuado para la depuración (porque, por ejemplo, puede distinguir la diferencia entre 1
, "1"
y "2\b1"
, que no puede imprimir sin inspect
).
p
también devuelve el valor del objeto, mientras puts
que no. 1.9.3p125 :002 > (p "foo").class "foo" => String 1.9.3p125 :003 > (puts "foo").class foo => NilClass
to_s
es el método estándar para encadenar en Ruby. inspect
. Como dije, es un método alternativo para cadenas, que produce una salida más adecuada para la depuración. Una vez completada la depuración, obviamente debe eliminar sus declaraciones de depuración (o para proyectos más serios, probablemente debería usar un marco de registro y no usar p o put para la depuración). El hecho de que p
devuelva el objeto parece irrelevante en la mayoría de las situaciones (y creo que di esta respuesta antes de que este fuera el caso). La diferencia en la salida es la diferencia principal (y solía ser la única).
También es importante tener en cuenta que puts
"reacciona" a una clase que ha to_s
definido, p
no lo hace. Por ejemplo:
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>
Esto se deduce directamente de la .inspect
llamada, pero no es obvio en la práctica.
p foo
es lo mismo que puts foo.inspect
puts
regresa nil
, en lugar de foo
como lo hace p
.
puts foo.inspect; foo
(-> {p "Hello World"}.call) == (-> {puts "Hello World".inspect}.call )
. ¡Muchos votos positivos NO hacen que esta sea una buena respuesta!
Además de las respuestas anteriores, hay una sutil diferencia en la salida de la consola, es decir, la presencia / ausencia de comillas / comillas invertidas, que puede ser útil:
p "+++++"
>> "+++++"
puts "====="
>> =====
Encuentro esto útil si desea hacer una barra de progreso simple, utilizando su pariente cercano, imprimir :
array = [lots of objects to be processed]
array.size
>> 20
Esto da la barra de progreso del 100%:
puts "*" * array.size
>> ********************
Y esto agrega un * incremental en cada iteración:
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
Escribe los objetos dados en ios. Escribe una nueva línea después de cualquiera que aún no termine con una secuencia de nueva línea. Devuelve nulo .
La secuencia debe estar abierta para escritura. Si se llama con un argumento de matriz , escribe cada elemento en una nueva línea. Cada objeto dado que no sea una cadena o matriz se convertirá llamando a su
to_s
método. Si se llama sin argumentos, genera una nueva línea nueva.
probémoslo en 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
Para cada objeto, escribe directamenteobj.inspect
seguido de una nueva línea en la salida estándar del programa.
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
Estos 2 son iguales:
p "Hello World"
puts "Hello World".inspect
( inspeccionar ofrece una vista más literal del objeto en comparación con el método to_s )
(->{p "Hello World"}.call) == (-> {puts "Hello World".inspect}.call )
Esto puede ilustrar una de las diferencias clave, que es que p
devuelve el valor de lo que se le pasa, donde se puts
devuelve 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']
Los programas de referencia puts
son más lentos
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)