Is instance instance possible?

Suppose I have a class like this:

class Test def test_func 140 end end 

And proc, which refers to a member function from Test :

 p = ->(x, y) { x + y + test_func } # => #<Proc:0x007fb3143e7f78@(pry):6 (lambda)> 

To call p , I bind it to the Test instance:

 test = Test.new # => #<Test:0x007fb3143c5a68> test.instance_exec(1, 2, &p) # => 143 

Now suppose I want to pass only y to p and always pass x = 1 :

 curried = p.curry[1] # => #<Proc:0x007fb3142be070 (lambda)> 

Ideally, I should have just instance_exec as before, but instead:

 test.instance_exec(2, &curried) => NameError: undefined local variable or method `test_func' for main:Object 

The process works in what seems like an incorrect binding. What gives?

+8
ruby currying
source share
1 answer

Yes, I think this is a mistake.

I think it comes down to curry returning a "C-level proc" rather than a regular proc. I don’t quite understand the difference between the two (I assume that the first is the code generated by the Ruby C code, which is curry ), but you can say that they are different when you try to take a binding.

 p.binding # => #<Binding:0x000000020b4238> curried.binding # => ArgumentError: Can't create a binding from C level Proc 

Looking at the source , it looks like their internal representations of the structure have different meanings for the iseq member, which says that this sequence of commands is preserved.

This is important when you call instance_exec , which ultimately calls invoke_block_from_c in vm.c , which leads to iseq type:

 else if (BUILTIN_TYPE(block->iseq) != T_NODE) { ... } else { return vm_yield_with_cfunc(th, block, self, argc, argv, blockptr); } 

A disconnected branch ( ... ) ends with a call to vm_push_frame , which looks like an environment where vm_yield_with_cfunc does not work.

So, I assume that since curry proc is created in C code and ends with a different β€œtype” than your first proc, another branch is taken in the above snippet and the environment is not used.

I must point out that all this is rather speculative, based on reading the code, I did not run any tests or tried anything (and I am also not so familiar with internal Ruby!)

+3
source share

All Articles