Project

General

Profile

Feature #14145

Updated by zverok (Victor Shepelev) almost 7 years ago

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) # => #<Method Klass#foo> 
 # after: 
 some_interesting_object.method(:foo) # => #<Method Klass#foo(first_arg, *other_args, keyword_arg:)> 
 ``` 

 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}"} = <default>" 
       when :keyreq then "#{name || "kw#{i+1}"}:" 
       when :key then "#{name || "kwparam#{i+1}"}: <default>" 
       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) 
 # => #<Method Array#at(param1)> 

 # Ruby method, proper param names 
 CGI.method(:escape) 
 # => #<Method CGI.escape(string)> 
 Addressable::URI.method(:parse) 
 # => #<Method Addressable::URI.parse(uri)> 
 Addressable::URI.method(:join) 
  => #<Method Addressable::URI.join(*uris)> 

 # We can't extract default values, but at least we can say they are there 
 Addressable::URI.method(:heuristic_parse) 
 # => #<Method Addressable::URI.heuristic_parse(uri, hints = <default>)> 
 ``` 

 If the proposal is accepted, I am ready to implement it properly in C (for all callable objects: `Method`, `UnboundMethod`, `Proc`)

Back