2009-08-10 13 views

Odpowiedz

286

p foo drukuje foo.inspect obserwowani przez nową linią, czyli wypisuje wartość inspect zamiast to_s, który jest bardziej odpowiedni do debugowania (bo można np odróżnić 1, "1" i "2\b1", czego nie, kiedy można drukowanie bez inspect).

+7

Tak, p (i kładzie) są zarówno w module jądra więc możesz zobaczyć szczegóły tutaj: http://www.ruby-doc.org/core/classes/Kernel.html#M005961 – mikej

+11

Zauważ, że 'p' również zwraca wartość obiektu, podczas gdy' puts' nie. '1.9.3p125: 002> (p" foo "). Class" foo "=> String 1.9.3p125: 003> (wstawia" foo ") class foo => NilClass' –

+2

Świetne podsumowanie dostarczone przez Garetha Reesa post zatytułowany ["Ruby p vs puts vs print"] (http://www.garethrees.co.uk/2013/05/04/p-vs-puts-vs-print-in-ruby/). – alexanderjsingleton

36

p foo jest taka sama jak puts foo.inspect

+3

ale 'puts' zwraca' nil', zamiast 'foo' tak samo jak' p'. – ribamar

+5

To źle. Jest to to samo, co 'put foo.inspect; foo' –

51

ważne jest również, aby pamiętać, że puts „reaguje” do klasy, która ma to_s zdefiniowany, p nie. Na przykład:

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> 

Wynika to bezpośrednio z połączenia .inspect, ale nie jest to oczywiste w praktyce.

1

Z ruby-2.4.1 document

umieszcza

puts(obj, ...) → nil

Zapisuje dany obiekt (ów) ios. Zapisuje nowy znak newline po tym, jak ten koniec nie jest już zakończony sekwencją nowej linii. Zwraca zero.

Strumień musi być otwarty do zapisu. Jeśli wywoływany z argumentem , zapisuje każdy element w nowej linii. Każdy podany obiekt, który nie jest łańcuchem lub tablicą, zostanie przekonwertowany przez wywołanie metody to_s . Jeśli zostanie wywołany bez argumentów, wypisze pojedynczy znak nowej linii.

spróbujmy go na 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

p(obj) → obj click to toggle source
p(obj1, obj2, ...) → [obj, ...] p() → nil
Dla każdego obiektu zapisuje bezpośrednio obj.inspect, a następnie znak nowej linii do standardowego wyjścia programu.

w 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 
1

Oprócz powyższych odpowiedzi, jest subtelne różnice w wydajności konsoli - mianowicie obecność/brak odwróconych znaków przecinki/notowań - które mogą być przydatne:

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

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

Uważam to przydatne, jeśli chcesz zrobić prosty pasek postępu, korzystając z ich bliskiego krewnego drukiem:

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

Daje to 100% pasek postępu:

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

I dodaje przyrostową * na każdej iteracji:

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 
>> ******