A cunning (evil?) trick with Ruby 4
One of the handy tools that Ruby makes available to us Domain Specific Pidgin builders is instance_eval. With instance_eval you can take a block that was created in one context, with all its lovely closed over local variables, and evaluate it in the context of an instance of an arbitrary object. Which means that any references to instance variables and calls to methods are made as if your block were a 0 argument method of that class. It’s really potent, but at the same time, a little frustrating.
Frustrating? Why frustrating?
Well, it would be really cool if you could call `instance_eval` with a block that took some arguments. That way, you could inject some values into the block from still another scope. (Yes, it’s arcane, but in the places where it would be handy it would be really handy).
I just worked out how to do it:
def my_instance_eval(*args, &block)
return instance_eval(*args,&block) unless block_given? && !block.arity.zero?
self.class.send(:define_method, :__, &block)
returning(__(*args)) do
self.class.send(:remove_method, :__)
end
endThere’s problems with that though, the most obvious one being that there’s no guarantee that __ won’t already exist as a method or that our block won’t call __. Here’s a safer, if scarier option:
def my_instance_eval(*args, &block)
return instance_eval(*args,&block) unless block_given? && !block.arity.zero?
old_method = (self.class.instance_method(:__) rescue nil)
self.class.send(:define_method, :__, &block)
block_method = self.class.instance_method(:__)
if old_method
self.class.send(:define_method, :__, old_method)
else
self.class.send(:remove_method, :__)
end
block_method.bind(self).call(*args)
endThis should work even in the face of being called with something along the lines of object.my_instance_eval(10) {|v| v + __}. Of course, there would be no point in calling like that. You’d only really need it when you want to do something like object.my_instance_eval(10,&a_block_param).
In the project I’m currently working, where the need for this arose, I shall probably extract the body of my_instance_eval to Proc#to_unbound_method, that way, instead of hanging onto Block objects I can hang onto UnboundMethod objects and avoid repeatedly shuffling methods.
But… how does it work?
I hope the code’s reasonably obvious. However…
The essence of it is that real methods get to take arguments, so what we need is some way of turning our block into a real method without altering the behaviour/interface of our object. Ruby does allow us create UnboundMethod objects which can be thought of as anonymous methods. To use them you have to bind them to a specific instance and then call them, which is the last thing we do in my_instance_eval. The intervening code is what turns our Proc into an UnboundMethod. First, we stash the old __ method, or a nil if there wasn’t one. Then we define a new __ using our block, and immediately use instance_method to get it back as an UnboundMethod. Then we either replace the old definition of __ or simply remove the new one, restoring the original behaviour of our class. Then we bind our new anonymous method to self and call it with our arguments. Easy.
Exercises for the interested reader
- What happens if our class has
method_removedormethod_addedimplemented? Can we ‘hide’ from them? How? - What does
Proc#to_unbound_methodlook like? Does it need to take an argument?

Any reason you can’t curry the block’s arguments?
block = lambda { lambda { |x| BODY } } obj.instance_eval(&block)[123]BODY will be evaluated within a context where self has been bound to obj, x_ has been bound to 123, and any free locals will remain bound to their respective values in _block’s closure.
Cheers,
Tom
That would work, but it pushes the ugliness to the wrong side of the interface.
In order to make that work, the caller has to do the double
lambdathing, rather than passing in a simple block.In the context I needed it (defining a validation block for an attribute) I wanted to be able to do:
Of course, I could do
But the ugliness ends up in the wrong place again.
OK. I didn’t know whether the blocks were being passed by the users of your interface or created by you in the implementation of your interface and thus open for currying. I figured it was worth a try.
Option 2: You could build on Facets’ Proc.bind (and avoid effects on method_added and friends to boot):
require 'rubygems' require 'facet/proc/bind' class Object def ie_w_args(*args, &block) block.bind(self)[*args] end endA quick test:
Foo = Struct.new(:instance_var) # keep an eye out for method additions class Foo; def self.method_added(m) p m end end foo = Foo.new("I'm foo's instance variable") foo.ie_w_args(123) { |x| puts [self, instance_var, x] }Cheers,
Tom
Ooh… that’s very nice.
Looking at the implementation, I wonder why it uses Thread?
I’ve found that curry trick remarkably useful in Javascript, by the way. It’s handy for setting up really private variables and methods for JavaScript objects: