I'm about 3 years late to this party, but I thought I'd share an approach that let's you treat the inner block more like a real block, rather than just a plain old argument.
The best way I know of to go about this is to create an object to act as a binding context and define the outer block as a method. So if I rewrite the original example as follows without the instance_exec call...
inner_proc = proc { puts "inner" }
outer_proc = proc { |*args, &inner_block|
puts *args
inner_block.call
puts "bar"
}
We can define outer_proc
as a method on an object
scope_object = Object.new
scope_object.define_singleton_method :bound_proc, &outer_proc
Now you can call scope_object.bound_proc
instead of the instance_exec
call above.
scope_object.bound_proc 1, 2, 3, &inner_proc
You'll get:
1
2
3
inner
bar
Unfortunately, you'll get a LocalJumpError if you try to yield inside of outer_proc
, rather than the inner_block.call
, I'm not entirely sure why. If someone has that answer then I'd be interested.