Feature #14609
`Kernel#p` without args shows the receiver
Description
Abstract¶
Kernel#p(obj)
prints obj as inspect
ed.
How about to show the receiver if an argument is not given?
Background¶
We recently introduce yield_self
which encourages block chain.
https://zverok.github.io/blog/2018-01-24-yield_self.html
Quoted 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 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,
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¶
obj.p
shows same as p(obj)
.
We can replace
block{...}.tap{|e| p e}
to
block{...}.p
For above example, we can simply add .p
at the end of 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 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.
Note¶
Past proposal and discussion¶
Endoh-san proposed same idea 10+ years ago 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 はどう動くのかとか(p selfと同じ、は変な気が) self.p(obj) はどうなのかとか。その辺が解決(納得)できたら、ということで。
English translation:
What the behavior of (I feel strange that it is similar to `p(self)`): p What happen on self.p(obj)
pp¶
If this proposal is accepted, we also need to change pp
behavior.
gems¶
tapp
method is provided by gem.
https://github.com/esminc/tapp
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.
History
#1
[ruby-core:86153]
Updated by mame (Yusuke Endoh) about 1 month ago
+1
Kernel#p
is one of the greatest feature in Ruby. It would be further great to make it useful.
#2
[ruby-core:86155]
Updated by zverok (Victor Shepelev) about 1 month 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.
#3
[ruby-core:86156]
Updated by Hanmac (Hans Mackowiak) about 1 month 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]