Forum: Ruby-core Proposal: Proc#bind

8a22582656f229ef0f4c3b8bc628cbcb?d=identicon&s=25 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.
Aaca034456897ccbc8bb14953c4a41c1?d=identicon&s=25 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
Aaca034456897ccbc8bb14953c4a41c1?d=identicon&s=25 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
0ec4920185b657a03edf01fff96b4e9b?d=identicon&s=25 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.
714df4094c6cc4a71b835b5ed3668f6b?d=identicon&s=25 Todd Fisher (taf2)
on 2012-05-06 03:06
myclosure = proc {|arg1,arg2,arg3|
  puts arg1 # => 'x'
  puts arg2 # => 'y'
  puts arg3 # => 'z'
}.bind("x","y","z")

# this is/would work just like the JavaScript Function.bind method

# see here:
https://developer.mozilla.org/en/JavaScript/Refere...

When using gems like EventMachine this would be handy...

I think it's not right to use a Proc#bind method to change self, just
use it like the JS equivalent to change the arguments passed to the proc
when it's called..

so sometime later calling:

myclosure.call

# it would be as if I had called it with:

myclosure.call('x','y','z')

# very useful... right?
This topic is locked and can not be replied to.