p vs pone en Ruby

270

¿Hay alguna diferencia entre py putsen Ruby?

collimarco
fuente

Respuestas:

334

p fooimprime foo.inspectseguido de una nueva línea, es decir, imprime el valor de en inspectlugar 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).

sepp2k
fuente
77
Sí, p (y pone) están en el módulo Kernel para que pueda ver los detalles aquí: ruby-doc.org/core/classes/Kernel.html#M005961
mikej
17
Tenga en cuenta que ptambién devuelve el valor del objeto, mientras putsque no. 1.9.3p125 :002 > (p "foo").class "foo" => String 1.9.3p125 :003 > (puts "foo").class foo => NilClass
Darren Cheng el
2
Gran resumen proporcionado por Gareth Rees en su publicación titulada "Ruby p vs pone vs imprimir" .
alexanderjsingleton
Un poco siento que esto me deja con una madriguera de preguntas. ¿Qué inspeccionar? ¿Qué es to_s? ¿Por qué quiero inspeccionar el texto impreso en lugar de una variable? ¿Cuál es más estándar para el mundo de la programación, debido a su mención de depuración, p o put? ¿Debería reemplazarse toda "p" con "put" al finalizar la depuración? Veo, en un comentario anterior, que p devuelve un objeto, lo cual es una gran diferencia. No estoy seguro de si esta respuesta está completa si solo menciona una pequeña diferencia que dará lugar a preguntas más grandes que aún responden a la pregunta original.
1
@AaronLoften to_ses 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 pdevuelva 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).
sepp2k
54

También es importante tener en cuenta que puts"reacciona" a una clase que ha to_sdefinido, pno 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 .inspectllamada, pero no es obvio en la práctica.

ezpz
fuente
37

p foo es lo mismo que puts foo.inspect

August Lilleaas
fuente
44
pero putsregresa nil, en lugar de foocomo lo hace p.
ribamar
10
Eso está mal. Es lo mismo queputs foo.inspect; foo
Eric Duminil
Esto demuestra que eres respuesta es incorrecta: (-> {p "Hello World"}.call) == (-> {puts "Hello World".inspect}.call ) . ¡Muchos votos positivos NO hacen que esta sea una buena respuesta!
lacostenycoder
3

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
>> ******
Jonathan_W
fuente
2

De documento ruby-2.4.1

pone

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

pags

p(obj) → obj click to toggle source
p(obj1, obj2, ...) → [obj, ...] p() → nil
Para cada objeto, escribe directamente obj.inspectseguido 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
fangxing
fuente
0

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 )

apadana
fuente
parecen iguales, pero NO lo son. Pruébelo:(->{p "Hello World"}.call) == (-> {puts "Hello World".inspect}.call )
lacostenycoder
0

Esto puede ilustrar una de las diferencias clave, que es que pdevuelve el valor de lo que se le pasa, donde se putsdevuelve 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 putsson 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)
lacostenycoder
fuente