Forum: Ruby wish list item: Method#to_proc

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
Bec38d63650c8912b6ba9b557fb953b9?d=identicon&s=25 Roger Pack (rogerdpack)
on 2008-11-23 00:26
would this be useful/theoretically possible?
UnboundMethod#to_proc
Thanks!
-=R
3399cbfb9e5fec93c324789b29309911?d=identicon&s=25 Pat Nakajima (patnakajima)
on 2008-11-23 00:55
(Received via mailing list)
On Nov 22, 6:22 pm, Roger Pack <rogerpack2...@gmail.com> wrote:
> would this be useful/theoretically possible?
> UnboundMethod#to_proc
> Thanks!
> -=R
> --
> Posted viahttp://www.ruby-forum.com/.

I put together an implementation here:
http://github.com/nakajima/rebound/tree/master/lib....
Not great, since it relies on Ruby2Ruby, but it worked for what I
needed, which was just to see if I could do it.
1bac2e65d64faf472cf2ebc94f0f5ee0?d=identicon&s=25 Ara Howard (ahoward)
on 2008-11-23 02:58
(Received via mailing list)
On Nov 22, 2008, at 4:22 PM, Roger Pack wrote:

> would this be useful/theoretically possible?
> UnboundMethod#to_proc
> Thanks!
> -=R


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/
Bec38d63650c8912b6ba9b557fb953b9?d=identicon&s=25 Roger Pack (rogerdpack)
on 2008-11-23 03:58
> cfp:~ > ruby a.rb
> #<UnboundMethod: M#m>
> 42
>
>
>
> the issues is, without binding, what is 'self' ???  once bound,
> to_proc exists.

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+an...
3399cbfb9e5fec93c324789b29309911?d=identicon&s=25 Pat Nakajima (patnakajima)
on 2008-11-23 06:10
(Received via mailing list)
On Nov 22, 8:52 pm, "ara.t.howard" <ara.t.how...@gmail.com> wrote:
>      bind(self).to_proc
>
>
> a @http://codeforpeople.com/
> --
> we can deny everything, except that we have the possibility of being  
> better. simply reflect on that.
> h.h. the 14th dalai lama

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.
703fbc991fd63e0e1db54dca9ea31b53?d=identicon&s=25 Robert Dober (Guest)
on 2008-11-23 11:51
(Received via mailing list)
On Sun, Nov 23, 2008 at 2:52 AM, ara.t.howard
<ara.t.howard@gmail.com>wrote:

>
> I guess you meant
bind( this ).to_proc

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

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

which on a quick thought seems impossible to have :(

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

It could be provided at call time, see example above. I kinda like the
idea.

Cheers
Robert

--
Ne baisse jamais la tête, tu ne verrais plus les étoiles.

Robert Dober ;)
1bac2e65d64faf472cf2ebc94f0f5ee0?d=identicon&s=25 Ara Howard (ahoward)
on 2008-11-23 18:17
(Received via mailing list)
On Nov 23, 2008, at 3:46 AM, Robert Dober wrote:

> but I guess OP rather wanted
>    M.i_m(:m).to_proc.call( self )
>
> which on a quick thought seems impossible to have :-(

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/
Bec38d63650c8912b6ba9b557fb953b9?d=identicon&s=25 Roger Pack (rogerdpack)
on 2008-12-01 20:59
Ara Howard wrote:
> On Nov 23, 2008, at 3:46 AM, Robert Dober wrote:
>
>> but I guess OP rather wanted
>>    M.i_m(:m).to_proc.call( self )
>>
>> which on a quick thought seems impossible to have :-(
>
> na, just have to perform the late binding in the caller's stead
> cfp:~ > ruby a.rb
> #<UnboundMethod: Object#m>
> 42

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'
This topic is locked and can not be replied to.