ruby-core@ruby-lang.org archive (unofficial mirror)
 help / color / mirror / Atom feed
* [ruby-core:84004] [Ruby trunk Feature#14145] Proposal: Better Method#inspect
       [not found] <redmine.issue-14145.20171130104208@ruby-lang.org>
@ 2017-11-30 10:42 ` zverok.offline
  2017-11-30 12:23 ` [ruby-core:84005] " shevegen
                   ` (28 subsequent siblings)
  29 siblings, 0 replies; 30+ messages in thread
From: zverok.offline @ 2017-11-30 10:42 UTC (permalink / raw)
  To: ruby-core

Issue #14145 has been reported by zverok (Victor Shepelev).

----------------------------------------
Feature #14145: Proposal: Better Method#inspect
https://bugs.ruby-lang.org/issues/14145

* 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) # => #<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)>

# 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`)



-- 
https://bugs.ruby-lang.org/

^ permalink raw reply	[flat|nested] 30+ messages in thread

* [ruby-core:84005] [Ruby trunk Feature#14145] Proposal: Better Method#inspect
       [not found] <redmine.issue-14145.20171130104208@ruby-lang.org>
  2017-11-30 10:42 ` [ruby-core:84004] [Ruby trunk Feature#14145] Proposal: Better Method#inspect zverok.offline
@ 2017-11-30 12:23 ` shevegen
  2017-11-30 14:39 ` [ruby-core:84007] " hanmac
                   ` (27 subsequent siblings)
  29 siblings, 0 replies; 30+ messages in thread
From: shevegen @ 2017-11-30 12:23 UTC (permalink / raw)
  To: ruby-core

Issue #14145 has been updated by shevegen (Robert A. Heiler).


I have nothing at all against better diagnostics, introspection etc...

However had, in that particular case that you showed above, I would
personally not want it, even though I normally am always in favour
of introspection. But to each their own - I have no problem if others
can use it. I should also note that my contra this is only mild, so
I ultimately would not have any real big objection to it either.

My proposal would be to allow this to be customized or customizable,
so that ruby hackers can decide on their own what they prefer.

One could use symbols to toggle the behaviour such as via:

:simple
:expanded

Where the latter may refer to the display that you described.

But I guess in most ways, it really depends on the personal
preferences of the ruby hacker. A good example how to solve 
this is one of my favourite gems of all times, the
did-you-mean gem. The toggle situation is to ... either use
the gem - or to uninstall it. :)

That way people can decide which variant they prefer.

Anyway, I don't want to make your suggestion too complex, 
since it really is simple - you propose a different default
display purpose, which is an ok suggestion to make. In 
general it would be nice if ruby could allow for more
customization and fine tuning of its internal behaviour
or parts; see also Martin's proposal to have unicode-related
stuff be easier debuggable; see also other suggestions to
make threads more easily debuggable (by default) and so on
and so forth. So I guess we can say that many people would
like to have more control, better messages, different
messages etc... - I guess the ruby core team has some things
to ponder about towards the path of ruby 3.x with all of
that. :)

PS: Perhaps for testing purposes, the above could be enabled
via a configure switch for post ruby 2.5.x, so that people
could test it, and give early feedback, and then also provide
more feedback here. The reason I mention this is because 
ruby 2.5.x changed a few things in regards to exceptions
and messages, such as underlining the error, changing the
stack trace display, etc... compared to ruby 2.4.x and I
think people may need some days or a few weeks to adjust
to it. Even adjusting to the did-you-mean gem took me a
while. :)

----------------------------------------
Feature #14145: Proposal: Better Method#inspect
https://bugs.ruby-lang.org/issues/14145#change-68086

* 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) # => #<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`)



-- 
https://bugs.ruby-lang.org/

^ permalink raw reply	[flat|nested] 30+ messages in thread

* [ruby-core:84007] [Ruby trunk Feature#14145] Proposal: Better Method#inspect
       [not found] <redmine.issue-14145.20171130104208@ruby-lang.org>
  2017-11-30 10:42 ` [ruby-core:84004] [Ruby trunk Feature#14145] Proposal: Better Method#inspect zverok.offline
  2017-11-30 12:23 ` [ruby-core:84005] " shevegen
@ 2017-11-30 14:39 ` hanmac
  2017-11-30 15:41 ` [ruby-core:84009] " zverok.offline
                   ` (26 subsequent siblings)
  29 siblings, 0 replies; 30+ messages in thread
From: hanmac @ 2017-11-30 14:39 UTC (permalink / raw)
  To: ruby-core

Issue #14145 has been updated by Hanmac (Hans Mackowiak).




@zverok some changes for your code: 
use Method#owner to get the class/module where the method is defined
that can make a difference for Singleton methods on a non-module object


Thema:

i think this change would be okay, but i am indifferent about the C-level funtions

for my bindings i do overload the methods depending on the type and amount of parameters
no need to show more of the code but this is the documenation block

~~~ cpp
/*
 * call-seq:
 *   contains?(x, y) -> bool
 *   contains?(point) -> bool
 *   contains?(rect) -> bool
 *
 * return true if the point or the rect is (not strictly) inside this rect
 * ===Arguments
 * * x and y are Integer
 * * pos is a WX::Point
 * * rect is a WX::Rect
 * ===Return value
 * bool
 *
 */
~~~

as you guys can see there are different cases,
because how ruby defines methods and use rb_scan_args,

my function returns parameters also just [:rest]


for most Ruby C-Api functions, there might be a way to make parameters return something useful,
but that's probably not the case for all functions

----------------------------------------
Feature #14145: Proposal: Better Method#inspect
https://bugs.ruby-lang.org/issues/14145#change-68089

* 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) # => #<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`)



-- 
https://bugs.ruby-lang.org/

^ permalink raw reply	[flat|nested] 30+ messages in thread

* [ruby-core:84009] [Ruby trunk Feature#14145] Proposal: Better Method#inspect
       [not found] <redmine.issue-14145.20171130104208@ruby-lang.org>
                   ` (2 preceding siblings ...)
  2017-11-30 14:39 ` [ruby-core:84007] " hanmac
@ 2017-11-30 15:41 ` zverok.offline
  2017-12-04  7:54 ` [ruby-core:84076] " ko1
                   ` (25 subsequent siblings)
  29 siblings, 0 replies; 30+ messages in thread
From: zverok.offline @ 2017-11-30 15:41 UTC (permalink / raw)
  To: ruby-core

Issue #14145 has been updated by zverok (Victor Shepelev).


@shevgen
> However had, in that particular case that you showed above, I would personally not want it.

Just curious: why? I mean, I'd understood "Don't think I need it", but to disgust it so much to propose having options for it -- why?.. Is it too verbose and therefore somehow painfully to read or what?.. If it would be introduced, how your life'll become worse?

----------------------------------------
Feature #14145: Proposal: Better Method#inspect
https://bugs.ruby-lang.org/issues/14145#change-68090

* 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) # => #<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`)



-- 
https://bugs.ruby-lang.org/

^ permalink raw reply	[flat|nested] 30+ messages in thread

* [ruby-core:84076] [Ruby trunk Feature#14145] Proposal: Better Method#inspect
       [not found] <redmine.issue-14145.20171130104208@ruby-lang.org>
                   ` (3 preceding siblings ...)
  2017-11-30 15:41 ` [ruby-core:84009] " zverok.offline
@ 2017-12-04  7:54 ` ko1
  2017-12-04  8:15 ` [ruby-core:84077] " hanmac
                   ` (24 subsequent siblings)
  29 siblings, 0 replies; 30+ messages in thread
From: ko1 @ 2017-12-04  7:54 UTC (permalink / raw)
  To: ruby-core

Issue #14145 has been updated by ko1 (Koichi Sasada).


I don't have strong opinions on your proposal, but source location information seems also helpful. Which is important or both?


----------------------------------------
Feature #14145: Proposal: Better Method#inspect
https://bugs.ruby-lang.org/issues/14145#change-68170

* 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) # => #<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`)



-- 
https://bugs.ruby-lang.org/

^ permalink raw reply	[flat|nested] 30+ messages in thread

* [ruby-core:84077] [Ruby trunk Feature#14145] Proposal: Better Method#inspect
       [not found] <redmine.issue-14145.20171130104208@ruby-lang.org>
                   ` (4 preceding siblings ...)
  2017-12-04  7:54 ` [ruby-core:84076] " ko1
@ 2017-12-04  8:15 ` hanmac
  2017-12-04 11:35 ` [ruby-core:84085] " zverok.offline
                   ` (23 subsequent siblings)
  29 siblings, 0 replies; 30+ messages in thread
From: hanmac @ 2017-12-04  8:15 UTC (permalink / raw)
  To: ruby-core

Issue #14145 has been updated by Hanmac (Hans Mackowiak).


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 didn't looked at the ruby source code for now, but might it be possible to implement source location for C-Api functions?
i don't care much about the line, but the so file would be cool

----------------------------------------
Feature #14145: Proposal: Better Method#inspect
https://bugs.ruby-lang.org/issues/14145#change-68172

* 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) # => #<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`)



-- 
https://bugs.ruby-lang.org/

^ permalink raw reply	[flat|nested] 30+ messages in thread

* [ruby-core:84085] [Ruby trunk Feature#14145] Proposal: Better Method#inspect
       [not found] <redmine.issue-14145.20171130104208@ruby-lang.org>
                   ` (5 preceding siblings ...)
  2017-12-04  8:15 ` [ruby-core:84077] " hanmac
@ 2017-12-04 11:35 ` zverok.offline
  2018-10-27 23:56 ` [ruby-core:89585] " guilhermekbsa
                   ` (22 subsequent siblings)
  29 siblings, 0 replies; 30+ messages in thread
From: zverok.offline @ 2017-12-04 11:35 UTC (permalink / raw)
  To: ruby-core

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) # => <Method #bar(limit, **options)>
# 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) # => #<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`)



-- 
https://bugs.ruby-lang.org/

^ permalink raw reply	[flat|nested] 30+ messages in thread

* [ruby-core:89585] [Ruby trunk Feature#14145] Proposal: Better Method#inspect
       [not found] <redmine.issue-14145.20171130104208@ruby-lang.org>
                   ` (6 preceding siblings ...)
  2017-12-04 11:35 ` [ruby-core:84085] " zverok.offline
@ 2018-10-27 23:56 ` guilhermekbsa
  2018-10-28  6:47 ` [ruby-core:89596] " eregontp
                   ` (21 subsequent siblings)
  29 siblings, 0 replies; 30+ messages in thread
From: guilhermekbsa @ 2018-10-27 23:56 UTC (permalink / raw)
  To: ruby-core

Issue #14145 has been updated by guilhermereiscampos (Guilherme Reis Campos).


zverok (Victor Shepelev) wrote:
> 
> # 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>)>
> ```
> 

I wonder why is not possible to extract the default values?  




----------------------------------------
Feature #14145: Proposal: Better Method#inspect
https://bugs.ruby-lang.org/issues/14145#change-74625

* 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) # => #<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`)



-- 
https://bugs.ruby-lang.org/

^ permalink raw reply	[flat|nested] 30+ messages in thread

* [ruby-core:89596] [Ruby trunk Feature#14145] Proposal: Better Method#inspect
       [not found] <redmine.issue-14145.20171130104208@ruby-lang.org>
                   ` (7 preceding siblings ...)
  2018-10-27 23:56 ` [ruby-core:89585] " guilhermekbsa
@ 2018-10-28  6:47 ` eregontp
  2018-10-28  9:10 ` [ruby-core:89599] " Ruby-Lang
                   ` (20 subsequent siblings)
  29 siblings, 0 replies; 30+ messages in thread
From: eregontp @ 2018-10-28  6:47 UTC (permalink / raw)
  To: ruby-core

Issue #14145 has been updated by Eregon (Benoit Daloze).


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.

FWIW, TruffleRuby already shows the source location in Method#inspect.

~~~
$ truffleruby -e 'p 1.method :times'
#<Method: Integer(Integer)#times .../truffleruby/src/main/ruby/core/integer.rb:89>
~~~

----------------------------------------
Feature #14145: Proposal: Better Method#inspect
https://bugs.ruby-lang.org/issues/14145#change-74634

* 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) # => #<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`)



-- 
https://bugs.ruby-lang.org/

^ permalink raw reply	[flat|nested] 30+ messages in thread

* [ruby-core:89599] [Ruby trunk Feature#14145] Proposal: Better Method#inspect
       [not found] <redmine.issue-14145.20171130104208@ruby-lang.org>
                   ` (8 preceding siblings ...)
  2018-10-28  6:47 ` [ruby-core:89596] " eregontp
@ 2018-10-28  9:10 ` Ruby-Lang
  2018-11-06 23:36 ` [ruby-core:89738] " keystonelemur
                   ` (19 subsequent siblings)
  29 siblings, 0 replies; 30+ messages in thread
From: Ruby-Lang @ 2018-10-28  9:10 UTC (permalink / raw)
  To: ruby-core

Issue #14145 has been updated by jwmittag (Jörg W Mittag).


guilhermereiscampos (Guilherme Reis Campos) wrote:
> zverok (Victor Shepelev) wrote:
> > ```ruby
> > # 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>)>
> > ```
> I wonder why is not possible to extract the default values?

Because they can be arbitrary Ruby code and Ruby is a Turing-complete language, which means that figuring out statically what the default value is, is equivalent to solving the Halting Problem. Additionally, Ruby is also capable of I/O and other side-effects, which means that the value can depend on external entities not visible to the documentation generator.

What would `Method#inspect` show for these:

```ruby
def foo(a = while true do; end) end

def bar(a = Time.now) end

def baz(a = if rand < 0.5 then 23 else 'fourty-two' end) end

def qux(a = File.read('somefile.txt')) end
```

And what about this:

```ruby
def crazy(a = FileUtils.rm_rf('/')) end
```

Would you expect `Method#inspect` to evaluate the default argument in order to be able to display its value?

Also, `Method#inspect` returns a `String`, but that loses all information about the type and structure of the default value:

```ruby
class Foo
  def inspect; '42' end
end

def foo(a = Foo.new) end

def bar(a = 42) end

method(:foo).inspect
#=> #<Method: Object#foo(a = 42)>

method(:bar).inspect
#=> #<Method: Object#bar(a = 42)>
```

We could copy the source text used to define the default argument into the output of `Method#inspect`, but that would require the source code to be available at runtime, which is a massive memory overhead (one `String` for every optional parameter in the entire system, and there is no upper bound on the size of that `String`, since a default argument can be any arbitrarily large Ruby program). Plus, there is the additional complication that not all methods in a Ruby system even *have* (Ruby) source code.

----------------------------------------
Feature #14145: Proposal: Better Method#inspect
https://bugs.ruby-lang.org/issues/14145#change-74637

* 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) # => #<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`)



-- 
https://bugs.ruby-lang.org/

^ permalink raw reply	[flat|nested] 30+ messages in thread

* [ruby-core:89738] [Ruby trunk Feature#14145] Proposal: Better Method#inspect
       [not found] <redmine.issue-14145.20171130104208@ruby-lang.org>
                   ` (9 preceding siblings ...)
  2018-10-28  9:10 ` [ruby-core:89599] " Ruby-Lang
@ 2018-11-06 23:36 ` keystonelemur
  2018-11-07  7:06 ` [ruby-core:89743] " nobu
                   ` (18 subsequent siblings)
  29 siblings, 0 replies; 30+ messages in thread
From: keystonelemur @ 2018-11-06 23:36 UTC (permalink / raw)
  To: ruby-core

Issue #14145 has been updated by baweaver (Brandon Weaver).


It may be possible to procify the arguments to self-contain them without really disturbing their integrity. `method(:name)` already returns a proc, so would it be wholly unexpected that the arguments may do the same?

Thinking out loud about potential implementations as per your idea:

```ruby
def foo(a = while true do; end) end

def bar(a = Time.now) end

def baz(a = if rand < 0.5 then 23 else 'fourty-two' end) end

def qux(a = File.read('somefile.txt')) end

method(:foo).default_values
=> { a: -> { while true do; end } }

method(:bar).default_values
=> { a: -> { Time.now } }

method(:qux).default_values
=> { a: -> { File.read('somefile.txt') } }

method(:baz).default_values
=> { a: -> { if rand < 0.5 then 23 else 'fourty-two' end } }
```

Amusingly this could almost be used as a setter as well, as is the way with Hashes default values:

```ruby
hash = {}

# value-based, same issue as with stated above, like the common `[]` issue
hash.default = 0

hash.default_proc = -> h, k { h[k] = [] }
```

So this is not unusual behavior as per Ruby standard implementation.

Consider a potential method implementation:

```ruby
method(:foo).default_values[:a]
=>  -> { while true do; end }

method(:foo).default_values[:a] = -> { while false do; end }
```

This could also be named `default_proc` but would not be as clear. I think this could yield some very interesting code down the road.

----------------------------------------
Feature #14145: Proposal: Better Method#inspect
https://bugs.ruby-lang.org/issues/14145#change-74781

* 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) # => #<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`)



-- 
https://bugs.ruby-lang.org/

^ permalink raw reply	[flat|nested] 30+ messages in thread

* [ruby-core:89743] [Ruby trunk Feature#14145] Proposal: Better Method#inspect
       [not found] <redmine.issue-14145.20171130104208@ruby-lang.org>
                   ` (10 preceding siblings ...)
  2018-11-06 23:36 ` [ruby-core:89738] " keystonelemur
@ 2018-11-07  7:06 ` nobu
  2018-11-07  8:35 ` [ruby-core:89746] " keystonelemur
                   ` (17 subsequent siblings)
  29 siblings, 0 replies; 30+ messages in thread
From: nobu @ 2018-11-07  7:06 UTC (permalink / raw)
  To: ruby-core

Issue #14145 has been updated by nobu (Nobuyoshi Nakada).


Ruby's default argument is not so simple as you think.

Where `foo` is defined as
```ruby
def foo(a, b = a.bar) end
```

from where should `method(:foo).default_values[:b]` refer `a`?


----------------------------------------
Feature #14145: Proposal: Better Method#inspect
https://bugs.ruby-lang.org/issues/14145#change-74785

* 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) # => #<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`)



-- 
https://bugs.ruby-lang.org/

^ permalink raw reply	[flat|nested] 30+ messages in thread

* [ruby-core:89746] [Ruby trunk Feature#14145] Proposal: Better Method#inspect
       [not found] <redmine.issue-14145.20171130104208@ruby-lang.org>
                   ` (11 preceding siblings ...)
  2018-11-07  7:06 ` [ruby-core:89743] " nobu
@ 2018-11-07  8:35 ` keystonelemur
  2019-01-10  5:02 ` [ruby-core:90967] " matz
                   ` (16 subsequent siblings)
  29 siblings, 0 replies; 30+ messages in thread
From: keystonelemur @ 2018-11-07  8:35 UTC (permalink / raw)
  To: ruby-core

Issue #14145 has been updated by baweaver (Brandon Weaver).


Good point. I can't think of a good solution to that that would not involve substantial work.

nobu (Nobuyoshi Nakada) wrote:
> Ruby's default argument is not so simple as you think.
> 
> Where `foo` is defined as
> ```ruby
> def foo(a, b = a.bar) end
> ```
> 
> from where should `method(:foo).default_values[:b]` refer `a`?



----------------------------------------
Feature #14145: Proposal: Better Method#inspect
https://bugs.ruby-lang.org/issues/14145#change-74789

* 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) # => #<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`)



-- 
https://bugs.ruby-lang.org/

^ permalink raw reply	[flat|nested] 30+ messages in thread

* [ruby-core:90967] [Ruby trunk Feature#14145] Proposal: Better Method#inspect
       [not found] <redmine.issue-14145.20171130104208@ruby-lang.org>
                   ` (12 preceding siblings ...)
  2018-11-07  8:35 ` [ruby-core:89746] " keystonelemur
@ 2019-01-10  5:02 ` matz
  2019-01-11  1:49 ` [ruby-core:91009] " ko1
                   ` (15 subsequent siblings)
  29 siblings, 0 replies; 30+ messages in thread
From: matz @ 2019-01-10  5:02 UTC (permalink / raw)
  To: ruby-core

Issue #14145 has been updated by matz (Yukihiro Matsumoto).


I agree with the concept of showing more information by `Method#inspect`. Patch welcome.

Matz.
 


----------------------------------------
Feature #14145: Proposal: Better Method#inspect
https://bugs.ruby-lang.org/issues/14145#change-76173

* 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) # => #<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`)



-- 
https://bugs.ruby-lang.org/

^ permalink raw reply	[flat|nested] 30+ messages in thread

* [ruby-core:91009] [Ruby trunk Feature#14145] Proposal: Better Method#inspect
       [not found] <redmine.issue-14145.20171130104208@ruby-lang.org>
                   ` (13 preceding siblings ...)
  2019-01-10  5:02 ` [ruby-core:90967] " matz
@ 2019-01-11  1:49 ` ko1
  2019-03-11  6:30 ` [ruby-core:91754] " ko1
                   ` (14 subsequent siblings)
  29 siblings, 0 replies; 30+ messages in thread
From: ko1 @ 2019-01-11  1:49 UTC (permalink / raw)
  To: ruby-core

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{} #=> #<Proc:0x00000298afcdb258@t.rb:1>`

```
class C
  def m
  end
end

p C.new.method(:m) #=> #<Method: C#m@/home/ko1/src/ruby/trunk/test.rb:3 >
```

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) # => #<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`)



-- 
https://bugs.ruby-lang.org/

^ permalink raw reply	[flat|nested] 30+ messages in thread

* [ruby-core:91754] [Ruby trunk Feature#14145] Proposal: Better Method#inspect
       [not found] <redmine.issue-14145.20171130104208@ruby-lang.org>
                   ` (14 preceding siblings ...)
  2019-01-11  1:49 ` [ruby-core:91009] " ko1
@ 2019-03-11  6:30 ` ko1
  2019-03-11 15:20 ` [ruby-core:91786] " zverok.offline
                   ` (13 subsequent siblings)
  29 siblings, 0 replies; 30+ messages in thread
From: ko1 @ 2019-03-11  6:30 UTC (permalink / raw)
  To: ruby-core

Issue #14145 has been updated by ko1 (Koichi Sasada).


Discussion at dev-meeting https://bugs.ruby-lang.org/issues/15614:

* eregon and ko1 want to show `source_location`.
  * with parameters? or without parameters?
  * ko1: I think parameters are too long to show with `source_location`
  * matz: `source_location` is longer than parameters.
  * several people are positive to show both.
* znz: `Proc#inspect` shows `source_lcoation`, so I want to know it on Method, too.

other discussion:

* how about to show rdoc entry?
  * github url?
  * show source code?
    * extend by clicking is cool, like on Jupyter environment.
  * extensible with gem?
* really useful to know parameters?



----------------------------------------
Feature #14145: Proposal: Better Method#inspect
https://bugs.ruby-lang.org/issues/14145#change-77030

* 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) # => #<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`)



-- 
https://bugs.ruby-lang.org/

^ permalink raw reply	[flat|nested] 30+ messages in thread

* [ruby-core:91786] [Ruby trunk Feature#14145] Proposal: Better Method#inspect
       [not found] <redmine.issue-14145.20171130104208@ruby-lang.org>
                   ` (15 preceding siblings ...)
  2019-03-11  6:30 ` [ruby-core:91754] " ko1
@ 2019-03-11 15:20 ` zverok.offline
  2019-03-13 20:21 ` [ruby-core:91819] " eregontp
                   ` (12 subsequent siblings)
  29 siblings, 0 replies; 30+ messages in thread
From: zverok.offline @ 2019-03-11 15:20 UTC (permalink / raw)
  To: ruby-core

Issue #14145 has been updated by zverok (Victor Shepelev).


I'd like to address this line from the dev log:

> ko1: I’m against to show the name of parameters.  we only need line no.  doesn’t it?
> matz: ask the original author.

I believe that I've already provided a use-case of my point of view, let me just repeat it: 

>  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) # => <Method #bar(limit, **options)>
# Oh!
obj.bar(3)
```
That's simple, **same-context flow**, which allows quick "pokin around".

The 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).

@ko1 doesn't it sound reasonable to you?

**Generally speaking** I believe that `#inspect`'s design goal is to provide enough, but not too much, information to understand "what is this object and how it can be used in the current context". I believe that `<Method #bar(limit, **options)>` follows this design goal -- "I know what I can do next with this object".

Next, I don't think "`Method` should have source location, because `Proc` has": for proc, it is typically the **only** way to tell one proc from another -- "it is a proc from that file", that's why "always visible" source location is important. For method, we have other means of identification and telling one from another (name, owner, receiver), and adding source location to it will make `#inspect`'s output just less readable.



----------------------------------------
Feature #14145: Proposal: Better Method#inspect
https://bugs.ruby-lang.org/issues/14145#change-77061

* 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) # => #<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`)



-- 
https://bugs.ruby-lang.org/

^ permalink raw reply	[flat|nested] 30+ messages in thread

* [ruby-core:91819] [Ruby trunk Feature#14145] Proposal: Better Method#inspect
       [not found] <redmine.issue-14145.20171130104208@ruby-lang.org>
                   ` (16 preceding siblings ...)
  2019-03-11 15:20 ` [ruby-core:91786] " zverok.offline
@ 2019-03-13 20:21 ` eregontp
  2019-03-14  6:45 ` [ruby-core:91827] " duerst
                   ` (11 subsequent siblings)
  29 siblings, 0 replies; 30+ messages in thread
From: eregontp @ 2019-03-13 20:21 UTC (permalink / raw)
  To: ruby-core

Issue #14145 has been updated by Eregon (Benoit Daloze).


My understanding is `#inspect` shows useful information for debugging, so then the source location is very useful, and gives me more than the parameters (e.g., I can find the code, documentation, etc from a file and line).

I'm not against showing parameters too, and it's encouraging it can easily be done from the information already existing for Method#parameters (as shown in the issue description).
So I think having both is nice.

----------------------------------------
Feature #14145: Proposal: Better Method#inspect
https://bugs.ruby-lang.org/issues/14145#change-77091

* 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) # => #<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`)



-- 
https://bugs.ruby-lang.org/

^ permalink raw reply	[flat|nested] 30+ messages in thread

* [ruby-core:91827] [Ruby trunk Feature#14145] Proposal: Better Method#inspect
       [not found] <redmine.issue-14145.20171130104208@ruby-lang.org>
                   ` (17 preceding siblings ...)
  2019-03-13 20:21 ` [ruby-core:91819] " eregontp
@ 2019-03-14  6:45 ` duerst
  2019-06-13  5:44 ` [ruby-core:93086] " nobu
                   ` (10 subsequent siblings)
  29 siblings, 0 replies; 30+ messages in thread
From: duerst @ 2019-03-14  6:45 UTC (permalink / raw)
  To: ruby-core

Issue #14145 has been updated by duerst (Martin Dürst).


Eregon (Benoit Daloze) wrote:
> My understanding is `#inspect` shows useful information for debugging, so then the source location is very useful, and gives me more than the parameters (e.g., I can find the code, documentation, etc from a file and line).

Yes indeed. A flexible console can even be set so that it can automatically parse the source location information and open the relevant file at the relevant position. Very convenient.

> I'm not against showing parameters too, and it's encouraging it can easily be done from the information already existing for Method#parameters (as shown in the issue description).
> So I think having both is nice.

Agreed.

----------------------------------------
Feature #14145: Proposal: Better Method#inspect
https://bugs.ruby-lang.org/issues/14145#change-77097

* 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) # => #<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`)



-- 
https://bugs.ruby-lang.org/

Unsubscribe: <mailto:ruby-core-request@ruby-lang.org?subject=unsubscribe>
<http://lists.ruby-lang.org/cgi-bin/mailman/options/ruby-core>

^ permalink raw reply	[flat|nested] 30+ messages in thread

* [ruby-core:93086] [Ruby trunk Feature#14145] Proposal: Better Method#inspect
       [not found] <redmine.issue-14145.20171130104208@ruby-lang.org>
                   ` (18 preceding siblings ...)
  2019-03-14  6:45 ` [ruby-core:91827] " duerst
@ 2019-06-13  5:44 ` nobu
  2019-07-14  7:01 ` [ruby-core:93747] [Ruby master " ko1
                   ` (9 subsequent siblings)
  29 siblings, 0 replies; 30+ messages in thread
From: nobu @ 2019-06-13  5:44 UTC (permalink / raw)
  To: ruby-core

Issue #14145 has been updated by nobu (Nobuyoshi Nakada).


ko1 (Koichi Sasada) wrote:
> ```patch
> +            VALUE loc_str = rb_sprintf("@%"PRIsVALUE":%"PRIsVALUE" ",
> +                                       RARRAY_AREF(loc, 0), RARRAY_AREF(loc, 1));
> +            rb_str_buf_append(str, loc_str);
> ```

You can use `rb_str_catf`.

----------------------------------------
Feature #14145: Proposal: Better Method#inspect
https://bugs.ruby-lang.org/issues/14145#change-78508

* 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) # => #<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`)



-- 
https://bugs.ruby-lang.org/

^ permalink raw reply	[flat|nested] 30+ messages in thread

* [ruby-core:93747] [Ruby master Feature#14145] Proposal: Better Method#inspect
       [not found] <redmine.issue-14145.20171130104208@ruby-lang.org>
                   ` (19 preceding siblings ...)
  2019-06-13  5:44 ` [ruby-core:93086] " nobu
@ 2019-07-14  7:01 ` ko1
  2019-07-14 13:39 ` [ruby-core:93760] " zn
                   ` (8 subsequent siblings)
  29 siblings, 0 replies; 30+ messages in thread
From: ko1 @ 2019-07-14  7:01 UTC (permalink / raw)
  To: ruby-core

Issue #14145 has been updated by ko1 (Koichi Sasada).

Status changed from Closed to Open

Now, I added source location information.
Adding parameter information is still open.

----------------------------------------
Feature #14145: Proposal: Better Method#inspect
https://bugs.ruby-lang.org/issues/14145#change-79387

* 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) # => #<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`)



-- 
https://bugs.ruby-lang.org/

^ permalink raw reply	[flat|nested] 30+ messages in thread

* [ruby-core:93760] [Ruby master Feature#14145] Proposal: Better Method#inspect
       [not found] <redmine.issue-14145.20171130104208@ruby-lang.org>
                   ` (20 preceding siblings ...)
  2019-07-14  7:01 ` [ruby-core:93747] [Ruby master " ko1
@ 2019-07-14 13:39 ` zn
  2019-07-14 17:58 ` [ruby-core:93762] " eregontp
                   ` (7 subsequent siblings)
  29 siblings, 0 replies; 30+ messages in thread
From: zn @ 2019-07-14 13:39 UTC (permalink / raw)
  To: ruby-core

Issue #14145 has been updated by znz (Kazuhiro NISHIYAMA).


`Method#inspect` separated by ` ` (a space) and `Proc#inspect` separated by `@`.
I think it is better to be unified, but I have no opinion on which is better.

```
% ruby -ve 'def m;end; p [method(:m), proc{}]'
ruby 2.7.0dev (2019-07-14T12:48:45Z trunk d8cc41c43b) [x86_64-darwin18]
[#<Method: main.m -e:1>, #<Proc:0x00007f850b8f9458@-e:1>]
```


----------------------------------------
Feature #14145: Proposal: Better Method#inspect
https://bugs.ruby-lang.org/issues/14145#change-79401

* 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) # => #<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`)



-- 
https://bugs.ruby-lang.org/

^ permalink raw reply	[flat|nested] 30+ messages in thread

* [ruby-core:93762] [Ruby master Feature#14145] Proposal: Better Method#inspect
       [not found] <redmine.issue-14145.20171130104208@ruby-lang.org>
                   ` (21 preceding siblings ...)
  2019-07-14 13:39 ` [ruby-core:93760] " zn
@ 2019-07-14 17:58 ` eregontp
  2019-07-30  7:07 ` [ruby-core:94025] " ko1
                   ` (6 subsequent siblings)
  29 siblings, 0 replies; 30+ messages in thread
From: eregontp @ 2019-07-14 17:58 UTC (permalink / raw)
  To: ruby-core

Issue #14145 has been updated by Eregon (Benoit Daloze).


znz (Kazuhiro NISHIYAMA) wrote:
> `Method#inspect` separated by ` ` (a space) and `Proc#inspect` separated by `@`.
> I think it is better to be unified, but I have no opinion on which is better.

I think ` ` (a space) is better, and it's what we use for Method#inspect in TruffleRuby.
My motivation is that selectionby double-clicking in the terminal just works with a space,
but fails with `@` and results in `0x00007f850b8f9458@-e` when double-clicking on the filename (`-e` here).
I find it also easier to read.

Anyone against changing `@` to ` ` (a space) in Proc#inspect?


----------------------------------------
Feature #14145: Proposal: Better Method#inspect
https://bugs.ruby-lang.org/issues/14145#change-79403

* 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) # => #<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`)



-- 
https://bugs.ruby-lang.org/

^ permalink raw reply	[flat|nested] 30+ messages in thread

* [ruby-core:94025] [Ruby master Feature#14145] Proposal: Better Method#inspect
       [not found] <redmine.issue-14145.20171130104208@ruby-lang.org>
                   ` (22 preceding siblings ...)
  2019-07-14 17:58 ` [ruby-core:93762] " eregontp
@ 2019-07-30  7:07 ` ko1
  2019-10-04 17:57 ` [ruby-core:95229] " richard.schneeman+ruby-lang
                   ` (5 subsequent siblings)
  29 siblings, 0 replies; 30+ messages in thread
From: ko1 @ 2019-07-30  7:07 UTC (permalink / raw)
  To: ruby-core

Issue #14145 has been updated by ko1 (Koichi Sasada).


> My motivation is that selection by double-clicking in the terminal just works with a space,

Good motivation!

----------------------------------------
Feature #14145: Proposal: Better Method#inspect
https://bugs.ruby-lang.org/issues/14145#change-80250

* 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) # => #<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`)



-- 
https://bugs.ruby-lang.org/

^ permalink raw reply	[flat|nested] 30+ messages in thread

* [ruby-core:95229] [Ruby master Feature#14145] Proposal: Better Method#inspect
       [not found] <redmine.issue-14145.20171130104208@ruby-lang.org>
                   ` (23 preceding siblings ...)
  2019-07-30  7:07 ` [ruby-core:94025] " ko1
@ 2019-10-04 17:57 ` richard.schneeman+ruby-lang
  2019-10-27 10:45 ` [ruby-core:95570] " zverok.offline
                   ` (4 subsequent siblings)
  29 siblings, 0 replies; 30+ messages in thread
From: richard.schneeman+ruby-lang @ 2019-10-04 17:57 UTC (permalink / raw)
  To: ruby-core

Issue #14145 has been updated by schneems (Richard Schneeman).


Thanks a ton for the proposal and feature. I love the idea of getting source location info by default! 

----------------------------------------
Feature #14145: Proposal: Better Method#inspect
https://bugs.ruby-lang.org/issues/14145#change-81903

* 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) # => #<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`)



-- 
https://bugs.ruby-lang.org/

^ permalink raw reply	[flat|nested] 30+ messages in thread

* [ruby-core:95570] [Ruby master Feature#14145] Proposal: Better Method#inspect
       [not found] <redmine.issue-14145.20171130104208@ruby-lang.org>
                   ` (24 preceding siblings ...)
  2019-10-04 17:57 ` [ruby-core:95229] " richard.schneeman+ruby-lang
@ 2019-10-27 10:45 ` zverok.offline
  2019-11-19  9:05 ` [ruby-core:95886] " ko1
                   ` (3 subsequent siblings)
  29 siblings, 0 replies; 30+ messages in thread
From: zverok.offline @ 2019-10-27 10:45 UTC (permalink / raw)
  To: ruby-core

Issue #14145 has been updated by zverok (Victor Shepelev).


This PR provides method parameters inspect: https://github.com/ruby/ruby/pull/2618
Implementation is most probably not optimal (to say the least), I am ready to fix it by comments. At least the tests and implementation should handle all possible cases.

Examples:

```ruby
def m(a, b=nil, *c, d:, e: nil, **rest, &block)
end

p method(:m)
#=> #<Method: m(a, b=<default>, *c, d:, e: <default>, **rest, &block) ...>

# Internal classes with param names not known:
p Array.instance_method(:slice)
#=> #<UnboundMethod: Array#slice(*)>
p Array.instance_method(:grep)
#=> #<UnboundMethod: Array(Enumerable)#grep(arg1)>
```

----------------------------------------
Feature #14145: Proposal: Better Method#inspect
https://bugs.ruby-lang.org/issues/14145#change-82351

* 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) # => #<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`)



-- 
https://bugs.ruby-lang.org/

^ permalink raw reply	[flat|nested] 30+ messages in thread

* [ruby-core:95886] [Ruby master Feature#14145] Proposal: Better Method#inspect
       [not found] <redmine.issue-14145.20171130104208@ruby-lang.org>
                   ` (25 preceding siblings ...)
  2019-10-27 10:45 ` [ruby-core:95570] " zverok.offline
@ 2019-11-19  9:05 ` ko1
  2019-11-19 18:42 ` [ruby-core:95887] " zverok.offline
                   ` (2 subsequent siblings)
  29 siblings, 0 replies; 30+ messages in thread
From: ko1 @ 2019-11-19  9:05 UTC (permalink / raw)
  To: ruby-core

Issue #14145 has been updated by ko1 (Koichi Sasada).


Great patch!
I think `<default>` is too long. How about `...`?

```
def foo9 a, b, o1=nil, *args, p1, k1:nil, rk1:, **kw, &bl
end
p method(:foo9)
#<Method: main.foo9(a, b, o1=..., *args, p1, rk1:, k1:..., **kw, &bl) /home/ko1/src/ruby/trunk/test.rb:20>
```

Another comment is `arg%d` can have meaning. How about `_`? I want to propose `_%d`, but it is used by numbered parameter...
(I understand `_` is not convenient because we need to count...). 


----------------------------------------
Feature #14145: Proposal: Better Method#inspect
https://bugs.ruby-lang.org/issues/14145#change-82722

* 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) # => #<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`)



-- 
https://bugs.ruby-lang.org/

^ permalink raw reply	[flat|nested] 30+ messages in thread

* [ruby-core:95887] [Ruby master Feature#14145] Proposal: Better Method#inspect
       [not found] <redmine.issue-14145.20171130104208@ruby-lang.org>
                   ` (26 preceding siblings ...)
  2019-11-19  9:05 ` [ruby-core:95886] " ko1
@ 2019-11-19 18:42 ` zverok.offline
  2019-11-20  0:41 ` [ruby-core:95888] " zverok.offline
  2019-11-20  4:43 ` [ruby-core:95891] " ko1
  29 siblings, 0 replies; 30+ messages in thread
From: zverok.offline @ 2019-11-19 18:42 UTC (permalink / raw)
  To: ruby-core

Issue #14145 has been updated by zverok (Victor Shepelev).


@ko1 I happened to sit next to Matz on speakers' lunch at RubyConf and asked him (just in case). He agreed to both of your proposals, so I'll change it in a day or two in my patch :)

Thank you!

----------------------------------------
Feature #14145: Proposal: Better Method#inspect
https://bugs.ruby-lang.org/issues/14145#change-82723

* 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) # => #<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`)



-- 
https://bugs.ruby-lang.org/

^ permalink raw reply	[flat|nested] 30+ messages in thread

* [ruby-core:95888] [Ruby master Feature#14145] Proposal: Better Method#inspect
       [not found] <redmine.issue-14145.20171130104208@ruby-lang.org>
                   ` (27 preceding siblings ...)
  2019-11-19 18:42 ` [ruby-core:95887] " zverok.offline
@ 2019-11-20  0:41 ` zverok.offline
  2019-11-20  4:43 ` [ruby-core:95891] " ko1
  29 siblings, 0 replies; 30+ messages in thread
From: zverok.offline @ 2019-11-20  0:41 UTC (permalink / raw)
  To: ruby-core

Issue #14145 has been updated by zverok (Victor Shepelev).


@ko1 I've updated the PR to use `...` and `_`, and rebased it from recent `master`.

----------------------------------------
Feature #14145: Proposal: Better Method#inspect
https://bugs.ruby-lang.org/issues/14145#change-82725

* 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) # => #<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`)



-- 
https://bugs.ruby-lang.org/

^ permalink raw reply	[flat|nested] 30+ messages in thread

* [ruby-core:95891] [Ruby master Feature#14145] Proposal: Better Method#inspect
       [not found] <redmine.issue-14145.20171130104208@ruby-lang.org>
                   ` (28 preceding siblings ...)
  2019-11-20  0:41 ` [ruby-core:95888] " zverok.offline
@ 2019-11-20  4:43 ` ko1
  29 siblings, 0 replies; 30+ messages in thread
From: ko1 @ 2019-11-20  4:43 UTC (permalink / raw)
  To: ruby-core

Issue #14145 has been updated by ko1 (Koichi Sasada).


merged. Thank you!

----------------------------------------
Feature #14145: Proposal: Better Method#inspect
https://bugs.ruby-lang.org/issues/14145#change-82730

* 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) # => #<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`)



-- 
https://bugs.ruby-lang.org/

^ permalink raw reply	[flat|nested] 30+ messages in thread

end of thread, other threads:[~2019-11-20  4:43 UTC | newest]

Thread overview: 30+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
     [not found] <redmine.issue-14145.20171130104208@ruby-lang.org>
2017-11-30 10:42 ` [ruby-core:84004] [Ruby trunk Feature#14145] Proposal: Better Method#inspect zverok.offline
2017-11-30 12:23 ` [ruby-core:84005] " shevegen
2017-11-30 14:39 ` [ruby-core:84007] " hanmac
2017-11-30 15:41 ` [ruby-core:84009] " zverok.offline
2017-12-04  7:54 ` [ruby-core:84076] " ko1
2017-12-04  8:15 ` [ruby-core:84077] " hanmac
2017-12-04 11:35 ` [ruby-core:84085] " zverok.offline
2018-10-27 23:56 ` [ruby-core:89585] " guilhermekbsa
2018-10-28  6:47 ` [ruby-core:89596] " eregontp
2018-10-28  9:10 ` [ruby-core:89599] " Ruby-Lang
2018-11-06 23:36 ` [ruby-core:89738] " keystonelemur
2018-11-07  7:06 ` [ruby-core:89743] " nobu
2018-11-07  8:35 ` [ruby-core:89746] " keystonelemur
2019-01-10  5:02 ` [ruby-core:90967] " matz
2019-01-11  1:49 ` [ruby-core:91009] " ko1
2019-03-11  6:30 ` [ruby-core:91754] " ko1
2019-03-11 15:20 ` [ruby-core:91786] " zverok.offline
2019-03-13 20:21 ` [ruby-core:91819] " eregontp
2019-03-14  6:45 ` [ruby-core:91827] " duerst
2019-06-13  5:44 ` [ruby-core:93086] " nobu
2019-07-14  7:01 ` [ruby-core:93747] [Ruby master " ko1
2019-07-14 13:39 ` [ruby-core:93760] " zn
2019-07-14 17:58 ` [ruby-core:93762] " eregontp
2019-07-30  7:07 ` [ruby-core:94025] " ko1
2019-10-04 17:57 ` [ruby-core:95229] " richard.schneeman+ruby-lang
2019-10-27 10:45 ` [ruby-core:95570] " zverok.offline
2019-11-19  9:05 ` [ruby-core:95886] " ko1
2019-11-19 18:42 ` [ruby-core:95887] " zverok.offline
2019-11-20  0:41 ` [ruby-core:95888] " zverok.offline
2019-11-20  4:43 ` [ruby-core:95891] " ko1

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).