wish list item: Method#to_proc

Discussion in 'Ruby' started by Roger Pack, Nov 22, 2008.

  1. Roger Pack

    Roger Pack Guest

    would this be useful/theoretically possible?
    UnboundMethod#to_proc
    Thanks!
    -=R
     
    Roger Pack, Nov 22, 2008
    #1
    1. Advertisements

  2. Roger Pack

    Pat Nakajima Guest

    Pat Nakajima, Nov 22, 2008
    #2
    1. Advertisements

  3. Roger Pack

    ara.t.howard Guest


    cfp:~ > cat a.rb
    class UnboundMethod
    def to_proc this = self
    bind(self).to_proc
    end
    end

    module M
    def m
    42
    end
    end

    include M

    p M.instance_method:)m)

    p M.instance_method:)m).to_proc(self).call



    cfp:~ > ruby a.rb
    #<UnboundMethod: M#m>
    42



    the issues is, without binding, what is 'self' ??? once bound,
    to_proc exists.

    a @ http://codeforpeople.com/
     
    ara.t.howard, Nov 23, 2008
    #3
  4. Roger Pack

    Roger Pack Guest

    Cool, though I'll admit I don't understand exactly everything that goes
    on in there :)

    My real goal is to be able to share methods from one class to another.

    I guess one could "share" methods from class to class [if the method
    originated from a module] by searching ancestor modules for a method and
    then 'cherry picking' it from the ancestor and including it [?]
    -=R

    http://eigenclass.org/hiki.rb?cmd=view&p=Rename+and+reject+methods+from+included+modules&key=eiffel
     
    Roger Pack, Nov 23, 2008
    #4
  5. Roger Pack

    Pat Nakajima Guest

    The main issue with this approach is that instances of UnboundMethod
    can only be bound to objects of the same class on which the method was
    originally defined. That's why I used Ruby2Ruby.
     
    Pat Nakajima, Nov 23, 2008
    #5
  6. Roger Pack

    Robert Dober Guest

    bind( this ).to_proc
    but I guess OP rather wanted
    M.i_m:)m).to_proc.call( self )

    which on a quick thought seems impossible to have :(
    It could be provided at call time, see example above. I kinda like the idea=
     
    Robert Dober, Nov 23, 2008
    #6
  7. Roger Pack

    ara.t.howard Guest

    na, just have to perform the late binding in the caller's stead


    cfp:~ > cat a.rb
    class UnboundMethod
    def to_proc
    lambda do |this, *a|
    bind(this).to_proc.call(*a)
    end
    end
    end

    class Object
    def m
    42
    end
    end


    p Object.instance_method:)m)
    p Object.instance_method:)m).to_proc.call(self)



    cfp:~ > ruby a.rb
    #<UnboundMethod: Object#m>
    42
    cfp:~ >


    other permutations, such as


    cfp:~ > cat a.rb
    class UnboundMethod
    def to_proc
    lambda{|*a| bind(this=self).to_proc.call(*a)}
    end
    end

    class Object
    def m() 42 end
    end

    p Object.instance_method:)m)
    p Object.instance_method:)m).to_proc.call


    cfp:~ > ruby a.rb
    #<UnboundMethod: Object#m>
    42


    which perform automatic late binding of self are also possible/
    preferrable

    of course there is the separate issue of what objects an unbound
    method can be attached to - but i think an orthogonal solution to
    that, plus something simple like the above, can handle most of the
    cases. also, ruby19 provides #owner in UnboundMethod, which is useful
    for this case i think.

    cheers.

    a @ http://codeforpeople.com/
     
    ara.t.howard, Nov 23, 2008
    #7
  8. Roger Pack

    Roger Pack Guest

    Wow that is dang cool.
    Next challenge:
    getting a method to transfer "easily" from one class to another [not
    directly related classes]. I guess you could do it if the method
    originated from a module--is that the only way?

    Ex:

    module AddToString
    def yoyo
    'within string func'
    end

    end

    class String
    include AddToString
    end

    class Object
    # attempt to find and 'borrow' a method from another class
    # in 1.8, method_name should be a string, in 1.9, not sure
    def borrow_and_run_method(from_this, method_name_desired)
    module_where_found = nil
    for ancestor in from_this.ancestors do
    module_where_found ||= ancestor if ancestor.class == Module &&
    ancestor.instance_methods.include?(method_name_desired)
    end
    raise unless module_where_found
    m = Module.new
    m.module_eval { include module_where_found}
    m.instance_methods.each{|method_name| m.module_eval{
    undef_method(method_name) unless method_name == method_name_desired } }
    # todo: double check we're not overwriting anything...
    self.extend m
    self.send method_name_desired
    end
    end

    class NoYoYo; end

    print NoYoYo.new.borrow_and_run_method(String, 'yoyo') # prints 'within
    string func'
     
    Roger Pack, Dec 1, 2008
    #8
    1. Advertisements

Ask a Question

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

You'll need to choose a username for the site, which only take a couple of moments (here). After that, you can post your question and our members will help you out.