Issue #14609 has been updated by sawa (Tsuyoshi Sawada).


What about `obj.tap`? Currently, `tap` without a block raises a `LocalJumpError`, so such extended feature of `tap` without a block would not have compatibility issues. Furthermore, the meaning of the word "tap", as well as the current usage of the method `tap` with a block, matches the use case we have here.

----------------------------------------
Feature #14609: Let `Kernel#p` without an argument print the receiver
https://bugs.ruby-lang.org/issues/14609#change-84204

* Author: ko1 (Koichi Sasada)
* Status: Open
* Priority: Normal
* Assignee: matz (Yukihiro Matsumoto)
----------------------------------------
# Abstract

`Kernel#p(obj)` prints `obj` as `inspect`ed.
How about printing the receiver if an argument is not given?

# Background

We recently introduced `yield_self`, which encourages block chain.

https://zverok.github.io/blog/2018-01-24-yield_self.html
Quoting from this article, we can write method chain with blocks:

```
construct_url
  .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 concerning debugging.
If we want to see the intermediate values in the method/block chain, we need to insert `tap{|e| p e}`.

With the above example,

```
construct_url
  .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}" }
```

# Proposal

Let `obj.p` work the same as `p(obj)`.

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

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

```
construct_url
  .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 issues

(1) Shorthand for `nil`

This spec change can introduce compatibility issues because `p` returns `nil` and does not output anything.
That is to say, `p` is a shorthand for `nil`. Some code-golfers use it.

Maybe we can ignore them :p

(2) make it a public method

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

# Note

## Past proposal and discussion

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

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

[ruby-dev:30903]

```
  p

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

  self.p(obj)

はどうなのかとか。その辺が解決(納得)できたら、ということで。
```

English translation:

```
What would the behavior of:

  p

be? (I feel strange for it to be equivalent to `p(self)`.) What would happen to

  self.p(obj)
```

## pp

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

## gems

`tapp` method is provided by a gem.
https://github.com/esminc/tapp 

I thought about proposing this method in core. But I found that `p` is shorter than `tapp`.
A disadvantage is that `p` is too short and difficult to grep.




-- 
https://bugs.ruby-lang.org/

Unsubscribe: <mailto:ruby-core-request / ruby-lang.org?subject=unsubscribe>
<http://lists.ruby-lang.org/cgi-bin/mailman/options/ruby-core>