Project

General

Profile

Feature #14609

Updated by sawa (Tsuyoshi Sawada) almost 2 years ago

# Abstract 

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

 # Background 

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

 https://zverok.github.io/blog/2018-01-24-yield_self.html 
 Quoting 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 concerning at debugging. 
 If we want to see the intermediate middle 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 shows same as `p(obj)`. 

 We can replace 
   `block{...}.tap{|e| p e}` 
 with 
   to  
   `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 issue 

 (1) Shorthand for `nil` 

 This spec change can introduce compatibility issues issue because `p` returns `nil` and does do not output anything. 
 That is to say, `p` is a shorthand for of `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 typo `obj.x` as to `obj.p` (not sure how it is feasible), it will raise a be `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 At 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? of (I feel strange for that it is similar to be equivalent to `p(self)`.) `p(self)`): 

   p 

 What would happen to on 

   self.p(obj) 
 ``` 

 ## pp 

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

 ## gems 

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

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

Back