Apakah ada perbedaan antara p
dan puts
di Ruby?
Apakah ada perbedaan antara p
dan puts
di Ruby?
Jawaban:
p foo
cetakan foo.inspect
diikuti oleh baris baru, yaitu mencetak nilai inspect
alih - 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
).
p
juga mengembalikan nilai objek, sementara puts
tidak. 1.9.3p125 :002 > (p "foo").class "foo" => String 1.9.3p125 :003 > (puts "foo").class foo => NilClass
to_s
adalah 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 p
mengembalikan 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).
Penting juga untuk dicatat bahwa puts
"bereaksi" ke kelas yang telah to_s
didefinisikan, p
tidak. 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 .inspect
panggilan, tetapi tidak jelas dalam praktiknya.
p foo
sama dengan puts foo.inspect
puts
kembali nil
, bukan foo
seperti halnya p
.
puts foo.inspect; foo
(-> {p "Hello World"}.call) == (-> {puts "Hello World".inspect}.call )
. Banyak upvotes TIDAK membuat ini jawaban yang bagus!
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
>> ******
Dari dokumen ruby-2.4.1
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
p(obj) → obj click to toggle source
p(obj1, obj2, ...) → [obj, ...]
p() → nil
Untuk setiap objek, tulis langsungobj.inspect
diikuti 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
Ini 2 adalah sama:
p "Hello World"
puts "Hello World".inspect
( inspect memberikan pandangan objek yang lebih literal dibandingkan dengan metode to_s )
(->{p "Hello World"}.call) == (-> {puts "Hello World".inspect}.call )
Ini dapat menggambarkan salah satu perbedaan utama yaitu p
mengembalikan nilai dari apa yang diteruskan ke sana, di mana sebagai puts
pengembalian 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 puts
lebih 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)