Issue #14914 has been updated by jeremyevans0 (Jeremy Evans).


ioquatix (Samuel Williams) wrote:
> What about some kind of currying? i.e. binding the block to the block you want to instance exec.

I'm not sure what you mean, could you elaborate with example code?

----------------------------------------
Feature #14914: Add BasicObject#instance_exec_with_block
https://bugs.ruby-lang.org/issues/14914#change-73453

* Author: jeremyevans0 (Jeremy Evans)
* Status: Open
* Priority: Normal
* Assignee: 
* Target version: 
----------------------------------------
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:

~~~ ruby
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.

~~~ ruby
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--------------------------------
0001-Add-BasicObject-instance_exec_with_block.patch (6.04 KB)


-- 
https://bugs.ruby-lang.org/

Unsubscribe: <mailto:ruby-core-request / ruby-lang.org?subject=unsubscribe>
<http://lists.ruby-lang.org/cgi-bin/mailman/options/ruby-core>