From: ko1@... Date: 2019-01-11T01:49:40+00:00 Subject: [ruby-core:91009] [Ruby trunk Feature#14145] Proposal: Better Method#inspect Issue #14145 has been updated by ko1 (Koichi Sasada). Eregon (Benoit Daloze) wrote: > 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 find source location (FILE:LINE) very valuable for debugging, e.g. to know if a method was overriden and to quickly check the source in my editor. +1. I'm using `#source_location` like `p method(:foo).source_location` sometimes to know the definition. If "Method#inspect" shows this information, it will help *me*. Also, `Proc#inspect` shows source location. `p proc{} #=> #` ``` class C def m end end p C.new.method(:m) #=> # ``` patch: ``` Index: proc.c =================================================================== --- proc.c (��������������� 66764) +++ proc.c (���������������) @@ -2681,6 +2681,16 @@ if (data->me->def->type == VM_METHOD_TYPE_NOTIMPLEMENTED) { rb_str_buf_cat2(str, " (not-implemented)"); } + + { + VALUE loc = rb_method_location(method); + if (!NIL_P(loc)) { + VALUE loc_str = rb_sprintf("@%"PRIsVALUE":%"PRIsVALUE" ", + RARRAY_AREF(loc, 0), RARRAY_AREF(loc, 1)); + rb_str_buf_append(str, loc_str); + } + } + rb_str_buf_cat2(str, ">"); return str; ``` ---------------------------------------- Feature #14145: Proposal: Better Method#inspect https://bugs.ruby-lang.org/issues/14145#change-76230 * 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: