From: zverok.offline@... Date: 2017-12-04T11:35:18+00:00 Subject: [ruby-core:84085] [Ruby trunk Feature#14145] Proposal: Better Method#inspect Issue #14145 has been updated by zverok (Victor Shepelev). ko1 (Koichi Sasada) wrote: > I don't have strong opinions on your proposal, but source location information seems also helpful. Which is important or both? I believe that source location is less necesary. I mean, what I had in mind was like "I am trying something in IRB/Debugger, and want to quickly experiment". This flow seems somehow natural to me: ```ruby obj = SomeNewLib.call_how_readme_shows obj.class # => SomeClass obj.methods # => [:foo, :bar] obj.method(:bar) # => # Oh! obj.bar(3) ``` That's simple, same-context flow, which allows quick "pokin around". Source location is NOT "same context" (you ask it to switch to the editor or fetch source some way), so for me it doesn't need to be "on the fingertips" (read: in `#inspect` output). ---------------------------------------- Feature #14145: Proposal: Better Method#inspect https://bugs.ruby-lang.org/issues/14145#change-68185 * Author: zverok (Victor Shepelev) * Status: Open * Priority: Normal * Assignee: * Target version: ---------------------------------------- The idea: When investigating (in example scripts, debugger or console) the library you are unfamiliar with, Ruby's reflection is very useful mechanism to understand "what it can": classes, modules, their constants, methods and so on. I propose to expose a bit more information Ruby has internally in `Method#inspect`: ```ruby # before: some_interesting_object.method(:foo) # => # # after: some_interesting_object.method(:foo) # => # ``` Dead-naive implementation: ```ruby class Method def signature recv = case receiver when Module "#{receiver.name}." else "#{receiver.class}#" end parameters.map.with_index { |(type, name), i| case type when :req then "#{name || "param#{i+1}"}" when :opt then "#{name || "param#{i+1}"} = " when :keyreq then "#{name || "kw#{i+1}"}:" when :key then "#{name || "kwparam#{i+1}"}: " when :rest then "*#{name || "rest"}" when :keyrest then "**#{name || "kwrest"}" end }.join(', ').prepend("#{recv}#{name}(") << ")" end def inspect "#<#{self.class.name} #{signature}>" end end ``` This works "sub-optimal" for methods implemented in C, yet pretty decently for Ruby-implemented methods: ```ruby # C method, default param names [1,2,3].method(:at) # => # # Ruby method, proper param names CGI.method(:escape) # => # Addressable::URI.method(:parse) # => # Addressable::URI.method(:join) => # # We can't extract default values, but at least we can say they are there Addressable::URI.method(:heuristic_parse) # => #)> ``` If the proposal is accepted, I am ready to implement it properly in C (for all callable objects: `Method`, `UnboundMethod`, `Proc`) -- https://bugs.ruby-lang.org/ Unsubscribe: