little tool for learning the ruby lookup path

Discussion in 'Ruby' started by timr, Jan 3, 2011.

  1. timr

    timr Guest

    I have been looking at the process ruby utilizes for method lookup,
    and wrote the code below. It has proven very enlightening to me. I am
    sharing. It allows obj#method_table to be called where one normally
    uses obj#methods. It inserts markers (conspicuous method names) into
    the method array that delimit the source for the listed methods up to
    that point so that it is clear how the method array is composed. See
    the test case at the bottom for clarification.

    The most thrilling thing I have done this entire year is to monkey-
    patch methods and see them hop to the appropriate section of the
    method_table and disappear from the previous position.

    I'd be interested to hear any feedback interested rubyists have about
    the approach or if anyone has suggestions to refactor the code.
    Thanks,
    Tim


    module Kernel
    def method_table
    #for completness sake, include the self in inh_chain, that way we
    can see the singleton_methods if any exist
    inh_chain = self.class.ancestors.unshift(self)

    inh_chain.each do |anc|
    meth_name = anc.to_s.center(20,'_')
    #define bookmark method to mark the position of that portion of
    the lookup path
    if anc.respond_to? :class_eval
    begin
    anc.class_eval("def #{meth_name}; end" )
    rescue
    end
    end
    if anc.respond_to?:)define_singleton_method)
    begin

    anc.define_singleton_method("singleton_to_left".to_s.center(25,'_').to_sym)
    {}
    #uncommnet the following line to see how subsequent
    singleton methods stack on

    #anc.define_singleton_method("Bsingleton".to_s.center(20,'').to_sym){}

    meth_name = "extension_to_right".to_s.center(25,'_').to_sym
    anc.extend(Module.new{eval("def #{meth_name};end")})

    #uncommnet the following lines to see how subsequent
    extended methods stack on
    #meth_name = "extension".to_s.center(20,'→').to_sym
    #anc.extend(Module.new{eval "def B#{meth_name};end;def
    C#{meth_name};end"})
    rescue
    end
    end
    end
    self.methods
    end
    end


    #######TEST CASE###########
    module First
    def added_in_first
    end
    end
    module Second
    def added_in_second
    end
    end
    class NewObject
    include First
    end
    no = NewObject.new
    no.extend(Second)
    def no.singleton_method
    end
    p no.method_table

    =>[:singleton_method, :____singleton_to_left____, :___extension_to_right____, :added_in_second, :_____NewObject______, :added_in_first, :_______First________, :_______Object_______, :nil?, :===, :=~, :!
    ~, :eql?, :class, :clone, :dup, :taint, :tainted?, :untaint, :untrust, :untrusted?, :trust, :freeze, :frozen?, :to_s, :inspect, :methods, :singleton_methods, :protected_methods, :private_methods, :public_methods, :instance_variables, :instance_variable_get, :instance_variable_set, :instance_variable_defined?, :instance_of?, :kind_of?, :is_a?, :tap, :send, :public_send, :respond_to?, :extend, :display, :method, :public_method, :define_singleton_method, :hash, :__id__, :eek:bject_id, :to_enum, :enum_for, :gem, :method_table,:_______Kernel_______, :==, :equal?, :!, :!
    =, :instance_eval, :instance_exec, :__send__, :____BasicObject_____]
    timr, Jan 3, 2011
    #1
    1. Advertising

  2. On Mon, Jan 3, 2011 at 10:05 AM, timr <> wrote:
    > I have been looking at the process ruby utilizes for method lookup,
    > and wrote the code below. It has proven very enlightening to me. I am
    > sharing. It allows obj#method_table to be called where one normally
    > uses obj#methods. It inserts markers (conspicuous method names) into
    > the method array that delimit the source for the listed methods up to
    > that point so that it is clear how the method array is composed. See
    > the test case at the bottom for clarification.
    >
    > The most thrilling thing I have done this entire year is to monkey-
    > patch methods and see them hop to the appropriate section of the
    > method_table and disappear from the previous position.


    IMHO monkey patching should not be general practice and stay limited
    to particular cases because of the dangers it creates.

    > I'd be interested to hear any feedback interested rubyists have about
    > the approach or if anyone has suggestions to refactor the code.


    What I don't like about your approach is that you _modify_ what you
    investigate. Analyzing where a method comes from should not change
    any of the classes involved.

    Then, I'd define this method as an instance method of Object because
    you want to investigate methods of a particular instance (even if it
    is a class or module).

    Finally, for classifying things a Hash seems a much better choice than an Array.

    I'd rather do something like this:

    require 'pp'

    class Object
    def method_table
    Hash.new {|h,k| h[k] = []}.tap do |tbl|
    methods.each do |m|
    tbl[method(m).owner] << m
    end
    end
    end
    end

    s = "foo"
    def s.bar;123;end

    pp s.method_table

    Kind regards

    robert

    --
    remember.guy do |as, often| as.you_can - without end
    http://blog.rubybestpractices.com/
    Robert Klemme, Jan 3, 2011
    #2
    1. Advertising

  3. timr

    timr Guest

    Hi Robert,
    Thanks for your massive improvements, and insights. I didn't like
    modifying the object during the investigation, but didn't know about
    obj#method(m).owner. I can't believe I hadn't seen that before. Your
    version is beautiful.
    Thanks for helping,
    Tim



    On Jan 3, 1:35 am, Robert Klemme <> wrote:
    > On Mon, Jan 3, 2011 at 10:05 AM, timr <> wrote:
    > > I have been looking at the process ruby utilizes for method lookup,
    > > and wrote the code below. It has proven very enlightening to me. I am
    > > sharing. It allows obj#method_table to be called where one normally
    > > uses obj#methods. It inserts markers (conspicuous method names) into
    > > the method array that delimit the source for the listed methods up to
    > > that point so that it is clear how the method array is composed. See
    > > the test case at the bottom for clarification.

    >
    > > The most thrilling thing I have done this entire year is to monkey-
    > > patch methods and see them hop to the appropriate section of the
    > > method_table and disappear from the previous position.

    >
    > IMHO monkey patching should not be general practice and stay limited
    > to particular cases because of the dangers it creates.
    >
    > > I'd be interested to hear any feedback interested rubyists have about
    > > the approach or if anyone has suggestions to refactor the code.

    >
    > What I don't like about your approach is that you _modify_ what you
    > investigate.  Analyzing where a method comes from should not change
    > any of the classes involved.
    >
    > Then, I'd define this method as an instance method of Object because
    > you want to investigate methods of a particular instance (even if it
    > is a class or module).
    >
    > Finally, for classifying things a Hash seems a much better choice than anArray.
    >
    > I'd rather do something like this:
    >
    > require 'pp'
    >
    > class Object
    >   def method_table
    >     Hash.new {|h,k| h[k] = []}.tap do |tbl|
    >       methods.each do |m|
    >         tbl[method(m).owner] << m
    >       end
    >     end
    >   end
    > end
    >
    > s = "foo"
    > def s.bar;123;end
    >
    > pp s.method_table
    >
    > Kind regards
    >
    > robert
    >
    > --
    > remember.guy do |as, often| as.you_can - without endhttp://blog.rubybestpractices.com/
    timr, Jan 3, 2011
    #3
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. jester.dev

    Learning c, need a little help with compiling.

    jester.dev, Feb 16, 2004, in forum: C Programming
    Replies:
    4
    Views:
    341
    jester.dev
    Feb 16, 2004
  2. ThaDoctor
    Replies:
    3
    Views:
    372
    Alan Woodland
    Sep 28, 2007
  3. Andrew Savige
    Replies:
    10
    Views:
    437
    Hrvoje Niksic
    Jan 11, 2008
  4. Mathieu Blondel
    Replies:
    0
    Views:
    94
    Mathieu Blondel
    Jun 20, 2005
  5. Daniel
    Replies:
    1
    Views:
    200
    Bart van Ingen Schenau
    Jul 9, 2013
Loading...

Share This Page