14

What is the purpose of having Method#unbind and UnboundMethod#bind?

From what I gather, methods are callable objects like procs and lambdas, except that methods are bound to the scope of their receiver:

class SomeClass
  def a_method; puts "from SomeClass"; end
end

s = SomeClass.new
s.a_method # => "from SomeClass"

I can call a_method if I'm within the context of SomeClass or if I have an object of SomeClass. I can make it a callable object by extracting the method as a Method object, yet it's still bound to an object of class SomeClass in this example:

m = s.method :a_method
m.class # => Method
m.owner # => SomeClass
m.call # => "from SomeClass"

Why would I want to unbind a method from its receiver? Maybe I can pass this around or bind it to a different object giving it new context, maybe I can have a completely different object call this method without inheritance, but I can't do anything with it unless I bind it to an object of its original class or I convert it to a Proc object (really a lambda, since methods and lambdas are somewhat similar):

# Module#instance_method gives me an UnboundMethod
ub = SomeClass.instance_method :a_method
ub.class # -> UnboundMethod

# now I can't make any calls 
ub.call # -> NoMethod Error, undefined method 'call'

class AnotherClass; end
a = AnotherClass.new
b = ub.bind(a) # -> TypeError: bind argument must be an instance of SomeClass
b = ub.bind(SomeClass.new).call # -> "from SomeClass"

I could convert the method object into a proc and maybe do something with it:

AnotherClass.class_eval do
  # I can access m becausec this block is evaluated in the same 
  # scope it's defined, so I can grab m ;)
  define_method(:method_from_some_class, m.to_proc)
end

AnotherClass.instance_methods(false) # -> [:method_from_some_class]
a.method_from_some_class # -> "from SomeClass"

What is the purpose of doing this? What are the real world applications for something like this?

sawa
  • 165,429
  • 45
  • 277
  • 381
Ellery Temple
  • 147
  • 1
  • 5
  • Welp... http://stackoverflow.com/questions/33708250/what-is-the-point-of-rubys-method-unbinding-mechanism – ndnenkov Jan 17 '16 at 23:04
  • 1
    I understand what they do,, but I will say that in 8 years of ruby programming, including occasional reflective metaprorgramming cleverness, I've never had to use `bind` on an unbound method, or done much with an unbound method at all. They are rarely needed. But good that they are there for complete reflective control in ruby. If you aren't seeing a use for them though, it's because the uses are rare for tricky things you'll know when you have one. If it's part of your day-to-day toolbox, you're probably being way too clever. – jrochkind Jan 20 '16 at 04:56

1 Answers1

15

It is indeed useful for metaprogramming. Suppose you want to know the location of the source code for SomeClass#method. If you can generate an instance of SomeClass, then you can create a (bound) method instance of it on that SomeClass instance, on which you can call various methods to investigate some meta-data of the method. But what if you did not know the method signature of SomeClass#new, or what if SomeClass's constructor method was named other than SomeClass#new? Just safely creating an instance of SomeClass can be difficult. That is where unbound method comes in handy. Without bothering with a particular instance of the class, or with how to create an instance, you can simply do SomeClass.instance_method(:a_method) (which is an unbound method), then call source_location on it to investigate the location of the definition:

unbound = SomeClass.instance_method(:a_method)
puts unbound.source_location

And when would this kind of metaprogramming be necessary in the real world applications? One example is when you are creating an IDE with functions for method lookup.

BenKoshy
  • 33,477
  • 14
  • 111
  • 80
sawa
  • 165,429
  • 45
  • 277
  • 381