Feature #14609

`Kernel#p` without args shows the receiver

Added by ko1 (Koichi Sasada) almost 2 years ago. Updated 11 months ago.

Target version:



Kernel#p(obj) prints obj as inspected.
How about to show the receiver if an argument is not given?


We recently introduce yield_self which encourages block chain.
Quoted from this article, we can write method chain with blocks:

  .yield_self { |url| Faraday.get(url) }.body
  .yield_self { |response| JSON.parse(response) }
  .dig('object', 'id')
  .yield_self { |id| id || '<undefined>' }
  .yield_self { |id| "server:#{id}" }

There is a small problem at debugging.
If we want to see the middle values in method/block chain, we need to insert tap{|e| p e}.

With above example,

  .yield_self { |url| Faraday.get(url) }.body
  .yield_self { |response| JSON.parse(response) }.tap{|e| p e} # debug print
  .dig('object', 'id')
  .yield_self { |id| id || '<undefined>' }.tap{|e| p e} # debug print
  .yield_self { |id| "server:#{id}" }


obj.p shows same as p(obj).

We can replace
block{...}.tap{|e| p e}

For above example, we can simply add .p at the end of line:

  .yield_self { |url| Faraday.get(url) }.body
  .yield_self { |response| JSON.parse(response) }.p # debug print
  .dig('object', 'id')
  .yield_self { |id| id || '<undefined>' }.p # debug print
  .yield_self { |id| "server:#{id}" }

Compatibility issue

(1) Shorthand for nil

This spec change can introduce compatibility issue because p returns nil and do not output anything.
That is to say, p is shorthand of nil. Some code-golfers use it.

Maybe we can ignore them :p

(2) make public method

Kernel#p is private method, so if we typo obj.x to obj.p (not sure how it is feasible), it will be NoMethodError because of visibility.
We need to change this behavior.


Past proposal and discussion

Endoh-san proposed same idea 10+ years ago [ruby-dev:29736] in Japanese.
I think we should revisit this idea because of yield_self introduction.

At this thread, Matz said "simple p shows p(self), it is not clear".



はどう動くのかとか(p selfと同じ、は変な気が)



English translation:

What the behavior of (I feel strange that it is similar to `p(self)`):


What happen on



If this proposal is accepted, we also need to change pp behavior.


tapp method is provided by gem.

I'd thought to propose this method into core. But I found that p is more shorter than tapp.
Disadvantage is p is too short and difficult to grep.

Related issues

Related to Ruby master - Feature #15112: Introducing the short form of `STDERR.puts expr.inspect`.OpenActions


Updated by mame (Yusuke Endoh) almost 2 years ago


Kernel#p is one of the greatest feature in Ruby. It would be further great to make it useful.

Updated by zverok (Victor Shepelev) almost 2 years ago

Small notice: If #13581 would be once acted upon, attaching p in the middle of the chain could be as simple as (using one of the proposed syntaxes)

  .yield_self { |response| JSON.parse(response) }.tap(&:.p)
  .dig('object', 'id')
  .yield_self { |id| id || '<undefined>' }.tap(&:.p)

Just .p is still nicer, though.

Updated by Hanmac (Hans Mackowiak) almost 2 years ago

hm i have a slightly problem with this

check out the different return types there:

a = []
p *a #=> nil

a = [1]
p *a #=> 1

a = [1,2]
p *a #=> [1,2]

Updated by ko1 (Koichi Sasada) over 1 year ago

Hanmac: do you rely on this behavior?

Updated by Hanmac (Hans Mackowiak) over 1 year ago

ko1 (Koichi Sasada) wrote:

Hanmac: do you rely on this behavior?

Me? not so much, in general i don't trust the return value of print commands (print returns null)

it was months ago, i probably wanted to point out that the return value of p might be differ depending on the parameters
It might be inconsistency?

There is Object.display too but i don't use it much because it doesn't have new lines

Updated by osyo (manga osyo) over 1 year ago

Good proposal.
This can solve the following problem.

# NG: syntax error, unexpected ':', expecting '}'
p { name: "homu", age: 14 }

# OK:
{ name: "homu", age: 14 }.p
# => {:name=>"homu", :age=>14}

Updated by nobu (Nobuyoshi Nakada) over 1 year ago

osyo (manga osyo) wrote:

Good proposal.
This can solve the following problem.

# NG: syntax error, unexpected ':', expecting '}'
p { name: "homu", age: 14 }

You can use parentheses.

p(name: "home", age: 14)

Updated by shevegen (Robert A. Heiler) over 1 year ago

I don't mind, personally. To me, the biggest improvement was
that we could omit doing:

require 'pp'


Since I did that a lot in my code. (I love pp; I think I use it
more than just p)

I personally have not been using (or needing) yield_self or tap so
far, so the change would probably not be of immediate benefit to
me; but probably also not require of me to change anything either.

To the name "tapp" - that name is a bit weird. To me it reads as
if we combine "tap" and then add a "p" to it. Reminds me of a
joke proposal to condense "end" into "enddd" and such. :D

To be fair, I consider the name yield_self to be also weird :D -
but matz added an alias called "then" to it if I understand it
correctly (though the semantic confuses me a bit as well ... but
I don't really want to distract here since I don't really feel
too strongly either way; picking good names is not always easy).

On a side note, perhaps in the long run we could have something
to "experiment" with - like new or changed features in ruby that
have not been 100% approved in the sense of a name AND the associated
functionality, so we can try them out for some time, which may help
build a stronger opinion either way. (I mean this in general, not
just in regards to #p here).

It may still be best to ask matz again though. Syntax shortcuts
(syntactic sugar) has always been an area in ruby where code changes
has happened (e. g. yield_self to then, or omitting the end value
for infinite ranges and so forth).

Updated by nobu (Nobuyoshi Nakada) over 1 year ago

How about:



Updated by matz (Yukihiro Matsumoto) over 1 year ago

I vote for #tapp.



Updated by mrkn (Kenta Murata) over 1 year ago

  • Related to Feature #15112: Introducing the short form of `STDERR.puts expr.inspect`. added

Updated by docx (Lukas Dolezal) over 1 year ago

Allowing debugging within yield_self is great! If yield_self was inspired by Elixir, we can look at Elixir for inspiration here as well:

One of the examples that is very interesting is that they have optional parameter to describe the printout:

[1, 2, 3]
|> IO.inspect(label: "before")
|> * 2))
|> IO.inspect(label: "after")
|> Enum.sum


before: [1, 2, 3]
after: [2, 4, 6]

I'm wondering, would that be something we would like in Ruby too?

The problem with the proposal of making obj.p is that the same method already is defined with parameter in the form of p(obj).

Hence it would be impossible to implement obj.p("after") - as that would conflict with the current version of p with parameter.

My feeling is that given that both yield_self and tap are defined on Object, it does not feel to me right that .p should be defined on Kernel. I can see the advantage of already existing method there, but I feel like it would be wrong overloading.

Continuing on the argument that yield_self is defined on Object, should we define this "print inspect and return self" method be defined on Object too?

If so, we could make new method p_self (terrible name yes) and implement it with new interface when called as instance method and avoid making Kernel.p public:

Object.p_self() - p self and return self
Object.p_self(label:) - puts "#{label}: #{self.inspect}" and return self

What do you think?

Updated by zverok (Victor Shepelev) over 1 year ago

docx (Lukas Dolezal) That are pretty interesting comparison with Elixir!
In fact, what the examples show (to me) is a need for more powerful partial application of procs. E.g. what would be a parity for Elixir is something like...

def p_with_label(label, obj)
  puts "#{label}#{obj.inspect}"

[1, 2, 3]
  .tap(&method(:p_with_label).curry['before: '])
  .map { |x| x * 2 }
  .tap(&method(:p_with_label).curry['after: '])

This example already works, yet doesn't look VERY expressive, to be honest. I see two pretty different solutions to the problem:

First is core. Considering the shorten of &method(:name) is discussed for ages (and almost agreed to be &, it could be discussed on addition of more powerful partial application than current (mostly unusable) Proc#curry to language core. The result may look somewhat like (fantasizing)...

[1, 2, 3]
  .tap(&:.p.with('before: '))
  .map { |x| x * 2 }
  .tap(&:.p.with('after: '))

The second one is rise of proc-producing libraries:

module Functional
  def inspect(label:)
    ->(obj) { puts "#{label}#{obj.inspect}" }

[1, 2, 3]
  .tap(&Functional.inspect(label: 'before: '))
  .map { |x| x * 2 }
  .tap(&Functional.inspect(label: 'after: '))

Updated by nobu (Nobuyoshi Nakada) over 1 year ago

zverok (Victor Shepelev) wrote:

First is core. Considering the shorten of &method(:name) is discussed for ages (and almost agreed to be &,

You may want to say &self.:name at
It wouldn't be able to omit the receiver, syntactically.

Updated by zverok (Victor Shepelev) over 1 year ago

It wouldn't be able to omit the receiver, syntactically.

Hmm, I missed this point is the discussion. This limitation makes :. syntax sugar substantially less useful :(

Updated by ko1 (Koichi Sasada) over 1 year ago

How about obj.p! or obj.pp! ?


Updated by naruse (Yui NARUSE) about 1 year ago

  • Target version deleted (2.6)

Updated by akr (Akira Tanaka) 11 months ago

matz (Yukihiro Matsumoto) wrote:

I vote for #tapp.

I don't like #tappp (for pp self ).

Updated by ko1 (Koichi Sasada) 11 months ago


  • obj.p has compatibility issue (some code expect p returns nil) -> reject
  • p! is not danger. -> reject
  • tapp seems long. tappp is weird
  • tap_p, tap_pp are too long.
  • introduce obj.? new method name -> don't modify syntax! (by matz). it is not predicate.

No conclusion.

Also available in: Atom PDF