Forum: Ruby-core [ruby-trunk - Feature #7836][Open] Need a way to get Method and UnboundMethod objects to methods ove

Posted by John Mair (banister)
on 2013-02-12 18:41
(Received via mailing list)
Issue #7836 has been reported by banister (john mair).

----------------------------------------
Feature #7836: Need a way to get Method and UnboundMethod objects to 
methods overridden by prepended modules
https://bugs.ruby-lang.org/issues/7836

Author: banister (john mair)
Status: Open
Priority: Normal
Assignee:
Category:
Target version:


See the following code:

module P
  def hello
    puts "from P"
    super
  end
end

class A
  def hello
    puts 'from A'
  end

  prepend P
end

A.instance_method(:hello).source_location == 
P.instance_method(:hello).source_location  #=> true

Discussion
----------

Since A.instance_method(:hello) effectively returns 
P.instance_method(:hello) it is impossible to get an UnboundMethod 
object to the original A#hello method.

Tools like [Pry](http://pryrepl.org) need to access UnboundMethod 
objects to every active method in the system for debugging purposes.

Possible solution
--------------

Simply allow instance_method() to take a second boolean parameter, 
indicating whether methods injected by prepended modules are to be 
included, it would default to true:

example:

A.instance_method(:hello) #=> same as P#hello
A.instance_method(:hello, false) #=> return strictly A#hello
Posted by Nobuyoshi Nakada (nobu)
on 2013-02-13 10:33
(Received via mailing list)
Issue #7836 has been updated by nobu (Nobuyoshi Nakada).

Description updated
ruby -v set to 2.0.0dev

It's a bug.
----------------------------------------
Bug #7836: Need a way to get Method and UnboundMethod objects to methods 
overridden by prepended modules
https://bugs.ruby-lang.org/issues/7836#change-36220

Author: banister (john mair)
Status: Open
Priority: Normal
Assignee:
Category:
Target version:
ruby -v: 2.0.0dev


=begin
See the following code:

  module P
    def hello
      puts "from P"
      super
    end
  end

  class A
    def hello
      puts 'from A'
    end

    prepend P
  end

  A.instance_method(:hello).source_location == 
P.instance_method(:hello).source_location  #=> true

== Discussion

Since (({A.instance_method(:hello)})) effectively returns 
(({P.instance_method(:hello)})) it is impossible to get an 
(({UnboundMethod})) object to the original (({A#hello})) method.

Tools like ((<[Pry]|URL:http://pryrepl.org>)) need to access 
(({UnboundMethod})) objects to every active method in the system for 
debugging purposes.

== Possible solution

Simply allow (({instance_method()})) to take a second boolean parameter, 
indicating whether methods injected by prepended modules are to be 
included, it would default to true:

example:

  A.instance_method(:hello) #=> same as P#hello
  A.instance_method(:hello, false) #=> return strictly A#hello

=end
Posted by marcandre (Marc-Andre Lafortune) (Guest)
on 2013-02-14 16:58
(Received via mailing list)
Issue #7836 has been updated by marcandre (Marc-Andre Lafortune).

Status changed from Closed to Open
Assignee set to matz (Yukihiro Matsumoto)

Matz, could you please confirm?

I'm not sure what is the right approach. What should 
A.instance_method(:hello) return:

1) the method that `A.new.hello` will execute, or
2) the method defined in A?

I feel that 1) is currently the case. Otherwise, strictly speaking, 
`String.instance_method(:object_id)` would raise a NameError!

I would expect:

  meth = A.instance_method :hello
  a = A.new
  meth.bind(a).call `# should be the same effect as a.bar
  meth.source_location ` # thus should be the same as 
a.method(:hello).source_location
  meth.owner ` # and thus should be the same as a.method(:hello).owner

This is currently true in Ruby 1.9, and this patch changes that.

I agree with John Mair that there should be a way to get the proper 
instance method of a class, as he suggests. I would add that 
String.instance_method(:object_id, false) should raise a NameError, as 
there is no such instance method defined in String.
----------------------------------------
Bug #7836: Need a way to get Method and UnboundMethod objects to methods 
overridden by prepended modules
https://bugs.ruby-lang.org/issues/7836#change-36291

Author: banister (john mair)
Status: Open
Priority: Normal
Assignee: matz (Yukihiro Matsumoto)
Category:
Target version:
ruby -v: 2.0.0dev


=begin
See the following code:

  module P
    def hello
      puts "from P"
      super
    end
  end

  class A
    def hello
      puts 'from A'
    end

    prepend P
  end

  A.instance_method(:hello).source_location == 
P.instance_method(:hello).source_location  #=> true

== Discussion

Since (({A.instance_method(:hello)})) effectively returns 
(({P.instance_method(:hello)})) it is impossible to get an 
(({UnboundMethod})) object to the original (({A#hello})) method.

Tools like ((<[Pry]|URL:http://pryrepl.org>)) need to access 
(({UnboundMethod})) objects to every active method in the system for 
debugging purposes.

== Possible solution

Simply allow (({instance_method()})) to take a second boolean parameter, 
indicating whether methods injected by prepended modules are to be 
included, it would default to true:

example:

  A.instance_method(:hello) #=> same as P#hello
  A.instance_method(:hello, false) #=> return strictly A#hello

=end
Posted by John Mair (banister)
on 2013-02-14 22:05
(Received via mailing list)
Issue #7836 has been updated by banister (john mair).


@ marcandre. Another possible approach is to provide 
`UnboundMethod#super`. We do something similar in our Method wrapper for 
Pry: https://github.com/pry/pry/blob/master/lib/pry/met...

While we're at it, other useful methods for `Method/UnboundMethod` could 
be private?, public?, aliases, singleton? :) but that could be asking 
for too much ;)

John
----------------------------------------
Bug #7836: Need a way to get Method and UnboundMethod objects to methods 
overridden by prepended modules
https://bugs.ruby-lang.org/issues/7836#change-36297

Author: banister (john mair)
Status: Open
Priority: Normal
Assignee: matz (Yukihiro Matsumoto)
Category:
Target version:
ruby -v: 2.0.0dev


=begin
See the following code:

  module P
    def hello
      puts "from P"
      super
    end
  end

  class A
    def hello
      puts 'from A'
    end

    prepend P
  end

  A.instance_method(:hello).source_location == 
P.instance_method(:hello).source_location  #=> true

== Discussion

Since (({A.instance_method(:hello)})) effectively returns 
(({P.instance_method(:hello)})) it is impossible to get an 
(({UnboundMethod})) object to the original (({A#hello})) method.

Tools like ((<[Pry]|URL:http://pryrepl.org>)) need to access 
(({UnboundMethod})) objects to every active method in the system for 
debugging purposes.

== Possible solution

Simply allow (({instance_method()})) to take a second boolean parameter, 
indicating whether methods injected by prepended modules are to be 
included, it would default to true:

example:

  A.instance_method(:hello) #=> same as P#hello
  A.instance_method(:hello, false) #=> return strictly A#hello

=end
Posted by Nobuyoshi Nakada (nobu)
on 2013-03-05 12:13
(Received via mailing list)
Issue #7836 has been updated by nobu (Nobuyoshi Nakada).

% Done changed from 100 to 0


----------------------------------------
Feature #7836: Need a way to get Method and UnboundMethod objects to 
methods overridden by prepended modules
https://bugs.ruby-lang.org/issues/7836#change-37298

Author: banister (john mair)
Status: Open
Priority: Normal
Assignee: matz (Yukihiro Matsumoto)
Category:
Target version:


=begin
See the following code:

  module P
    def hello
      puts "from P"
      super
    end
  end

  class A
    def hello
      puts 'from A'
    end

    prepend P
  end

  A.instance_method(:hello).source_location == 
P.instance_method(:hello).source_location  #=> true

== Discussion

Since (({A.instance_method(:hello)})) effectively returns 
(({P.instance_method(:hello)})) it is impossible to get an 
(({UnboundMethod})) object to the original (({A#hello})) method.

Tools like ((<[Pry]|URL:http://pryrepl.org>)) need to access 
(({UnboundMethod})) objects to every active method in the system for 
debugging purposes.

== Possible solution

Simply allow (({instance_method()})) to take a second boolean parameter, 
indicating whether methods injected by prepended modules are to be 
included, it would default to true:

example:

  A.instance_method(:hello) #=> same as P#hello
  A.instance_method(:hello, false) #=> return strictly A#hello

=end
Posted by Nobuyoshi Nakada (nobu)
on 2013-03-05 12:33
(Received via mailing list)
Issue #7836 has been updated by nobu (Nobuyoshi Nakada).

File 0001-proc.c-include-prepended-method-flag.patch added


----------------------------------------
Feature #7836: Need a way to get Method and UnboundMethod objects to 
methods overridden by prepended modules
https://bugs.ruby-lang.org/issues/7836#change-37300

Author: banister (john mair)
Status: Open
Priority: Normal
Assignee: matz (Yukihiro Matsumoto)
Category:
Target version:


=begin
See the following code:

  module P
    def hello
      puts "from P"
      super
    end
  end

  class A
    def hello
      puts 'from A'
    end

    prepend P
  end

  A.instance_method(:hello).source_location == 
P.instance_method(:hello).source_location  #=> true

== Discussion

Since (({A.instance_method(:hello)})) effectively returns 
(({P.instance_method(:hello)})) it is impossible to get an 
(({UnboundMethod})) object to the original (({A#hello})) method.

Tools like ((<[Pry]|URL:http://pryrepl.org>)) need to access 
(({UnboundMethod})) objects to every active method in the system for 
debugging purposes.

== Possible solution

Simply allow (({instance_method()})) to take a second boolean parameter, 
indicating whether methods injected by prepended modules are to be 
included, it would default to true:

example:

  A.instance_method(:hello) #=> same as P#hello
  A.instance_method(:hello, false) #=> return strictly A#hello

=end
Posted by marcandre (Marc-Andre Lafortune) (Guest)
on 2013-03-05 18:38
(Received via mailing list)
Issue #7836 has been updated by marcandre (Marc-Andre Lafortune).


banister (john mair) wrote:
> @ marcandre. Another possible approach is to provide `UnboundMethod#super`.

Not a bad idea, for Method also, although I'm not sure if it would be 
useful to many. You might want to make another feature request for this 
(and provide a decent justification!).

> While we're at it, other useful methods for `Method/UnboundMethod` could be 
private?, public?, aliases, singleton? :) but that could be asking for too much ;)

These might be more problematic:

* privacy
It is not really an attribute of the method itself. It's an attribute of 
the class, i.e. does the class provide public access to a method.

    class F
      def priv; end
      alias_method :pub, :priv
      private :priv
    end
    F.new.pub # => nil
    F.new.priv # => NoMethodError: private method `priv' called
    F.instance_method(:pub) == F.instance_method(:priv) # => true

So I think that Module#private_method_defined? and 
Module#private_instance_methods are the ones you want to use.

* aliases
Not sure who would use this, but you can already easily do this by 
comparing the unbound methods:

    String.instance_methods.group_by{|x| 
String.instance_method(x)}.map(&:last).reject(&:one?)
     # => [[:==, :===], [:[], :slice], [:length, :size], [:succ, :next], 
[:succ!, :next!], [:to_s, :to_str], [:concat, :<<],
               [:intern, :to_sym], [:kind_of?, :is_a?], [:send, 
:__send__], [:object_id, :__id__], [:to_enum, :enum_for]]

Or if you prefer:

    class UnboundMethod
      def aliases
        owner.instance_methods.select{|m| owner.instance_method(m) == 
self}
      end
    end

     String.instance_method(:size).aliases # => [:length, :size]

* singleton?

This is a property of the owner, no? Module#singleton_class? already 
accepted: https://bugs.ruby-lang.org/issues/7609

So if you really want, you will be able to roll your own easily:

    class UnboundMethod
      def singleton?
        owner.is_a?(Class) && owner.singleton_class?
      end
    end


----------------------------------------
Feature #7836: Need a way to get Method and UnboundMethod objects to 
methods overridden by prepended modules
https://bugs.ruby-lang.org/issues/7836#change-37311

Author: banister (john mair)
Status: Open
Priority: Normal
Assignee: matz (Yukihiro Matsumoto)
Category:
Target version:


=begin
See the following code:

  module P
    def hello
      puts "from P"
      super
    end
  end

  class A
    def hello
      puts 'from A'
    end

    prepend P
  end

  A.instance_method(:hello).source_location == 
P.instance_method(:hello).source_location  #=> true

== Discussion

Since (({A.instance_method(:hello)})) effectively returns 
(({P.instance_method(:hello)})) it is impossible to get an 
(({UnboundMethod})) object to the original (({A#hello})) method.

Tools like ((<[Pry]|URL:http://pryrepl.org>)) need to access 
(({UnboundMethod})) objects to every active method in the system for 
debugging purposes.

== Possible solution

Simply allow (({instance_method()})) to take a second boolean parameter, 
indicating whether methods injected by prepended modules are to be 
included, it would default to true:

example:

  A.instance_method(:hello) #=> same as P#hello
  A.instance_method(:hello, false) #=> return strictly A#hello

=end
Posted by marcandre (Marc-Andre Lafortune) (Guest)
on 2013-03-05 18:40
(Received via mailing list)
Issue #7836 has been updated by marcandre (Marc-Andre Lafortune).

Category set to core
Target version set to current: 2.1.0

nobu: Patch looks good, but I would go further and have 
`String.instance_method(:object_id, false)` also raise a NameError, for 
consistency with `String.instance_methods(false).include? :object_id # 
=> false`.

Did Matz confirm any of this?
----------------------------------------
Feature #7836: Need a way to get Method and UnboundMethod objects to 
methods overridden by prepended modules
https://bugs.ruby-lang.org/issues/7836#change-37312

Author: banister (john mair)
Status: Open
Priority: Normal
Assignee: matz (Yukihiro Matsumoto)
Category: core
Target version: current: 2.1.0


=begin
See the following code:

  module P
    def hello
      puts "from P"
      super
    end
  end

  class A
    def hello
      puts 'from A'
    end

    prepend P
  end

  A.instance_method(:hello).source_location == 
P.instance_method(:hello).source_location  #=> true

== Discussion

Since (({A.instance_method(:hello)})) effectively returns 
(({P.instance_method(:hello)})) it is impossible to get an 
(({UnboundMethod})) object to the original (({A#hello})) method.

Tools like ((<[Pry]|URL:http://pryrepl.org>)) need to access 
(({UnboundMethod})) objects to every active method in the system for 
debugging purposes.

== Possible solution

Simply allow (({instance_method()})) to take a second boolean parameter, 
indicating whether methods injected by prepended modules are to be 
included, it would default to true:

example:

  A.instance_method(:hello) #=> same as P#hello
  A.instance_method(:hello, false) #=> return strictly A#hello

=end
Posted by prijutme4ty (Ilya Vorontsov) (Guest)
on 2013-03-08 22:53
(Received via mailing list)
Issue #7836 has been updated by prijutme4ty (Ilya Vorontsov).


Also it should be mentioned that there is no way to get Method for super 
call. So one cannot know, for example, number of argments of method down 
the ancestry chain. For prepending methods there is a workaround - to 
save link on prepend_features. Or to maintain full hierarchy of methods, 
but it looks akward.
E.g. I needed such method when created #coerce(other,meth) prepending 
either usual #coerce(other) method or already defined 
#coerce(other,meth). It's hard to know whether prepended module should 
call super with one or two arguments.
----------------------------------------
Feature #7836: Need a way to get Method and UnboundMethod objects to 
methods overridden by prepended modules
https://bugs.ruby-lang.org/issues/7836#change-37404

Author: banister (john mair)
Status: Open
Priority: Normal
Assignee: matz (Yukihiro Matsumoto)
Category: core
Target version: current: 2.1.0


=begin
See the following code:

  module P
    def hello
      puts "from P"
      super
    end
  end

  class A
    def hello
      puts 'from A'
    end

    prepend P
  end

  A.instance_method(:hello).source_location == 
P.instance_method(:hello).source_location  #=> true

== Discussion

Since (({A.instance_method(:hello)})) effectively returns 
(({P.instance_method(:hello)})) it is impossible to get an 
(({UnboundMethod})) object to the original (({A#hello})) method.

Tools like ((<[Pry]|URL:http://pryrepl.org>)) need to access 
(({UnboundMethod})) objects to every active method in the system for 
debugging purposes.

== Possible solution

Simply allow (({instance_method()})) to take a second boolean parameter, 
indicating whether methods injected by prepended modules are to be 
included, it would default to true:

example:

  A.instance_method(:hello) #=> same as P#hello
  A.instance_method(:hello, false) #=> return strictly A#hello

=end
Please log in before posting. Registration is free and takes only a minute.
Existing account (Switch to SSL-encrypted connection)
NEW: Do you have a Google/GoogleMail or Yahoo account? No registration required!
Log in with Google account | Log in with Yahoo account
No account? Register here.