p vs menempatkan di Ruby

270

Apakah ada perbedaan antara pdan putsdi Ruby?

collimarco
sumber

Jawaban:

334

p foocetakan foo.inspectdiikuti oleh baris baru, yaitu mencetak nilai inspectalih - alih to_s, yang lebih cocok untuk debugging (karena Anda dapat misalnya membedakan antara 1, "1"dan "2\b1", yang Anda tidak dapat saat mencetak tanpa inspect).

sepp2k
sumber
7
Yap, p (dan put) keduanya dalam modul Kernel sehingga Anda dapat melihat detailnya di sini: ruby-doc.org/core/classes/Kernel.html#M005961
mikej
17
Perhatikan bahwa pjuga mengembalikan nilai objek, sementara putstidak. 1.9.3p125 :002 > (p "foo").class "foo" => String 1.9.3p125 :003 > (puts "foo").class foo => NilClass
Darren Cheng
2
Ringkasan hebat diberikan oleh Gareth Rees dalam postingannya yang berjudul "Ruby p vs puts vs print" .
alexanderjsingleton
Agak merasa seperti ini membuat saya dengan lubang pertanyaan kelinci. Apa yang diperiksa? Whats to_s? Mengapa saya ingin memeriksa teks cetak dan bukan variabel? Mana yang lebih standar untuk dunia pemrograman, karena Anda menyebutkan debugging, p atau menempatkan? Haruskah semua "p" diganti dengan "menempatkan" setelah selesai debugging ?? Saya melihat, dalam komentar di atas, bahwa p mengembalikan objek, yang merupakan perbedaan besar. Saya tidak yakin apakah jawaban ini selesai jika hanya menyebutkan perbedaan kecil yang akan mengarah pada pertanyaan yang lebih besar yang masih menjawab pertanyaan aslinya.
1
@AaronLoften to_sadalah metode to-string standar di Ruby. inspect. seperti yang saya katakan, adalah metode alternatif ke-string, yang menghasilkan output yang lebih cocok untuk debugging. Setelah menyelesaikan debugging Anda harus menghapus pernyataan debugging Anda (atau untuk proyek yang lebih serius Anda mungkin harus menggunakan kerangka kerja logging dan tidak menggunakan p atau menempatkan untuk debugging sama sekali). Fakta yang pmengembalikan objek tampaknya tidak relevan dalam kebanyakan situasi (dan saya percaya saya memberikan jawaban ini sebelum ini terjadi). Perbedaan dalam output adalah perbedaan utama (dan dulunya satu-satunya).
sepp2k
54

Penting juga untuk dicatat bahwa puts"bereaksi" ke kelas yang telah to_sdidefinisikan, ptidak. Sebagai contoh:

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>

Ini mengikuti langsung dari .inspectpanggilan, tetapi tidak jelas dalam praktiknya.

ezpz
sumber
37

p foo sama dengan puts foo.inspect

Lilleaas Agustus
sumber
4
tetapi putskembali nil, bukan fooseperti halnya p.
ribamar
10
Itu salah. Itu sama denganputs foo.inspect; foo
Eric Duminil
Ini membuktikan bahwa jawaban yang sedang tidak benar: (-> {p "Hello World"}.call) == (-> {puts "Hello World".inspect}.call ) . Banyak upvotes TIDAK membuat ini jawaban yang bagus!
lacostenycoder
3

Selain jawaban di atas, ada perbedaan halus dalam output konsol - yaitu ada / tidak adanya tanda koma / tanda kutip - yang dapat berguna:

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

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

Saya menemukan ini berguna jika Anda ingin membuat progress bar sederhana, menggunakan kerabat dekatnya, cetak :

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

Ini memberikan bilah kemajuan 100%:

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

Dan ini menambahkan * inkremental pada setiap iterasi:

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
sumber
2

Dari dokumen ruby-2.4.1

menempatkan

puts(obj, ...) → nil

Menulis objek yang diberikan ke ios. Menulis baris baru setelah yang belum berakhir dengan urutan baris baru. Pengembalian nihil .

Aliran harus dibuka untuk ditulis. Jika dipanggil dengan argumen array , tulis setiap elemen pada baris baru. Setiap objek yang diberikan bukan string atau array akan dikonversi dengan memanggil to_s metodenya. Jika dipanggil tanpa argumen, menghasilkan satu baris baru.

ayo coba di 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

hal

p(obj) → obj click to toggle source
p(obj1, obj2, ...) → [obj, ...] p() → nil
Untuk setiap objek, tulis langsung obj.inspectdiikuti oleh baris baru ke output standar program.

di 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
sumber
0

Ini 2 adalah sama:

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

( inspect memberikan pandangan objek yang lebih literal dibandingkan dengan metode to_s )

apadana
sumber
mereka tampak sama, tetapi TIDAK. Cobalah:(->{p "Hello World"}.call) == (-> {puts "Hello World".inspect}.call )
lacostenycoder
0

Ini dapat menggambarkan salah satu perbedaan utama yaitu pmengembalikan nilai dari apa yang diteruskan ke sana, di mana sebagai putspengembalian 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']

Pertunjukan benchmark putslebih lambat

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
sumber