Forum: Ruby-core Proposal: Proc#bind

Posted by Paweł Kondzior (pkondzior)
on 2008-12-18 01:14
(Received via mailing list)
It would be good to have Proc#bind(receiver) method that returns new 
Proc
with changed self. Right now to accomplish this in ruby 1.8 we can do 
this
using unbound methods, but this can leak memory:

Current 1.8.X implementation:

class Proc #:nodoc:
  def bind(object)
    block, time = self, Time.now
    (class << object; self end).class_eval do
      method_name = "__bind_#{time.to_i}_#{time.usec}"
      define_method(method_name, &block)
      method = instance_method(method_name)
      remove_method(method_name)
      method
    end.bind(object)
  end
end

Ofcourse it's possible to do this better using `instnace_exec` with 
empty
lambda {} but we can't figure out from context what arguments was set, 
what
not, and what have default value, we just must remaber it and always 
repeat
it in new lambda.

self => some_singlethon_method_of_class_A

some_proc = Proc.new { |a,b=1| puts self.inspect }

To change self we just need to create new lambda with instance exec:

self => some_singlethon_method_of_class_B

new_proc_with_changed_self = lambda { |a, b=1| self.instance_exec(*args,
&some_proc) }

But it's slower, and we need to implement alway same |*args| as in old
lambda.

Doing just:

some_proc.bind(self)

, as we have in unbound methods will be easy and fast as hell.
Posted by Radosław Bułat (radarek)
on 2008-12-18 14:15
(Received via mailing list)
As far as I understand Pawel proporsal he wants to do smth like this:

proc = Proc.new { puts self.inspect }
a = [1, 2, 3]
h = { "foo" => "bar" }
s = "foo"

p_a = proc.bind(a)
p_h = proc.bind(h)
p_s = proc.bind(s)

p_a.call # => [1, 2, 3]
p_h.call # => {"foo" => "bar"}
p_s.call # => "foo"


I know that in ruby 1.8/1.9 i can do this:

 class Proc
   def bind(other)
     return Proc.new do
         other.instance_eval(&self)
     end
   end
 end

and it will work:

proc.bind([]).call
proc.bind({}).call

But the problem is in implementation because it create some chain. It
call's original proc with instance_eval. So after several
proc.bind(...).bind(...) we have some unnecessary calls.

Is there any problem to add this to Ruby core? Maybe some issue with
implementing it? I guess it shouldn't because for example class
UnboundedMethod have #bind method and Method have #unbind method. It
should works like this (but probably #unbind doesn't make sens because
there is no such thing like UnboundedProc).

Any comments on this? Matz and the rest?
--
Pozdrawiam

Rados³aw Bu³at
http://radarek.jogger.pl - mój blog
Posted by Radosław Bułat (radarek)
on 2008-12-18 14:19
(Received via mailing list)
Maybe #bind is misleading because there is already bounded "self".
Maybe #change_self would be better or #build_with(self) or other good
name.


--
Pozdrawiam

Rados³aw Bu³at
http://radarek.jogger.pl - mój blog
Posted by Yukihiro Matsumoto (Guest)
on 2008-12-18 14:52
(Received via mailing list)
Hi,

In message "Re: [ruby-core:20642] Re: Proposal: Proc#bind"
    on Thu, 18 Dec 2008 22:05:59 +0900, 
"=?ISO-8859-2?Q?Rados=B3aw_Bu=B3at?=" <radek.bulat@gmail.com> writes:

|Is there any problem to add this to Ruby core? Maybe some issue with
|implementing it? I guess it shouldn't because for example class
|UnboundedMethod have #bind method and Method have #unbind method. It
|should works like this (but probably #unbind doesn't make sens because
|there is no such thing like UnboundedProc).
|
|Any comments on this? Matz and the rest?

I am not sure whether it is good to add every possible method to the
core.  Since you can define it by Ruby itself, I'd like to see if it
works well or not.  I don't see good enough use-case for this method
yet.

              matz.
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.