From: lukas@... Date: 2018-10-13T13:57:52+00:00 Subject: [ruby-core:89400] [Ruby trunk Feature#14609] `Kernel#p` without args shows the receiver Issue #14609 has been updated by docx (Lukas Dolezal). Allowing debugging within `yield_self` is great! If `yield_self` was inspired by Elixir, we can look at Elixir for inspiration here as well: https://hexdocs.pm/elixir/IO.html#inspect/2 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") |> Enum.map(&(&1 * 2)) |> IO.inspect(label: "after") |> Enum.sum ``` Prints: ``` 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 can keep the name `Object.p` and implement it with new interface when called as instance method and avoid making `Kernel.p` public: ``` Object.p() - p self.inspect and return self Object.p(label:) - p "#{label}: #{self.inspect}" and return self ``` What do you think? ---------------------------------------- Feature #14609: `Kernel#p` without args shows the receiver https://bugs.ruby-lang.org/issues/14609#change-74439 * Author: ko1 (Koichi Sasada) * Status: Open * Priority: Normal * Assignee: matz (Yukihiro Matsumoto) * Target version: 2.6 ---------------------------------------- # 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 || '' } .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 || '' }.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 || '' }.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 [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". [ruby-dev:30903] ``` 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. -- https://bugs.ruby-lang.org/ Unsubscribe: