加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

ruby – 可能instance_eval一个curried proc?

发布时间:2020-12-16 19:09:04 所属栏目:百科 来源:网络整理
导读:假设我有一个这样的类: class Test def test_func 140 endend 还有一个proc,它引用了Test中的成员函数: p = -(x,y) { x + y + test_func } # = #Proc:0x007fb3143e7f78@(pry):6 (lambda) 要调用p,我将它绑定到Test的一个实例: test = Test.new # = #Test:
假设我有一个这样的类:
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级proc”而不是正常proc的事实.我不完全理解两者之间的区别(我猜测前者是由Ruby C代码创建的,这是curry所做的),但是当你尝试接受绑定时,你可以告诉它们是不同的.

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

通过查看the source,看起来它们的内部结构表示对于iseq成员具有不同的值,该成员表示该块所具有的指令序列类型.

当你调用instance_exec时这很重要,它最终在vm.c中调用invoke_block_from_c,它根据iseq类型进行分支:

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

我错过的分支(…)最终调用vm_push_frame,看起来像某些环境,而vm_yield_with_cfunc没有.

所以我的猜测是因为curried的proc是用C代码创建的,并且结果与你的第一个proc不同,所以另一个分支是在上面的代码片段中使用的,并且不使用环境.

我应该指出,所有这些都是基于阅读代码的非常推测,我没有运行任何测试或尝试过任何东西(而且我也不是那么熟悉内部Ruby!)

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读