Feature #14914
closedAdd BasicObject#instance_exec_with_block
Description
Currently, you cannot use instance_exec
with a block that requires a block argument. If you have a block that requires a block argument and you want to get the equivalent of instance_exec
, you have to do something like:
singleton_class.define_method(:temporary_method_name, &block)
send(:temporary_method_name, *args, &block_arg)
singleton_class.remove_method(:temporary_method_name)
That approach doesn't work for frozen objects, making it impossible to get the equivalent of instance_exec
for a frozen object if you have a block that requires a block argument.
The attached patch implements instance_exec_with_block
, which is the same as instance_exec
, except the last argument must be a Proc
which is passed as the block argument instead of the regular argument to the block.
1.instance_exec_with_block(42, 2, proc{|x| self * x}) do |a, b, &blk|
(self + a).instance_exec(b, &blk)
end
# => 86
This method cannot be implemented in a gem because it requires changes to vm.c
and vm_eval.c
to implement. There wasn't a function allowing you to provide both a cref and a block argument when evaluating a block (hence the addition of vm_yield_with_cref_and_block
in the patch).
There are alternative APIs that could support this feature. One approach would be adding support for :args
and :block_arg
keyword arguments to instance_eval
(if no regular arguments are given).
Files