繁体   English   中英

可以对instance_eval进行咖喱处理吗?

[英]Possible to instance_eval a curried proc?

假设我有一个这样的课:

class Test
  def test_func
    140
  end
end

还有一个proc,它引用了Test的成员函数:

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

要调用p ,我将其绑定到Test一个实例:

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

现在假设我只想将y传递给p ,并且始终传递x = 1

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

理想情况下,我应该能够像以前一样只使用instance_exec ,但是:

test.instance_exec(2, &curried)

=> NameError: undefined local variable or method `test_func' for main:Object

proc运行在似乎是不正确的绑定中。 是什么赋予了?

是的,我相信这是一个错误。

我认为可以归结为以下事实: curry返回“ C level proc”而不是常规proc。 我不完全理解两者之间的区别(我猜前者是由Ruby C代码创建的,而curry正是这样做的),但是当您尝试进行绑定时,您可以告诉他们它们是不同的。

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

通过查看源代码 ,看起来它们的内部结构表示形式对于iseq成员而言具有不同的值,该值表示此块持有哪种指令序列。

当你调用这是显著instance_exec ,最终结束调用invoke_block_from_cvm.c ,这取决于分支iseq类型:

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

我错过的分支( ... )最终以类似于vm_yield_with_cfunc没有的环境的方式调用vm_push_frame

因此,我的猜测是,因为咖喱的proc是用C代码创建的,并且结局的类型与您的第一个proc不同,所以上面的代码段采用了另一个分支,并且不使用环境。

我要指出的是,这一切是相当投机基于阅读的代码,我没有运行任何测试或尝试新鲜事物出来(我也没有那么熟悉内部红宝石反正!)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM