gpt4 book ai didi

ruby - 可能对 curry 过程进行 instance_eval 吗?

转载 作者:数据小太阳 更新时间:2023-10-29 06:54:38 25 4
gpt4 key购买 nike

假设我有这样一个类:

class Test
def test_func
140
end
end

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

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

要调用 p,我将它绑定(bind)到 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 在似乎不正确的绑定(bind)中运行。给了什么?

最佳答案

是的,我认为这是一个错误。

我认为这归结为 curry 返回“C 级过程”而不是正常过程这一事实。我不完全理解两者之间的区别(我猜前者是由 Ruby C 代码创建的,这是 curry 所做的),但是当您尝试绑定(bind)。

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

通过查看 the source , 这看起来它们的内部结构表示对于 iseq 成员有不同的值,它说明了这个 block 包含什么样的指令序列。

这在您调用 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 没有.

所以我的猜测是,因为柯里化(Currying)过程是用 C 代码创建的,并且以与您的第一个过程不同的“类型”结束,所以另一个分支在上面的代码片段中被采用​​并且没有使用环境。

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

关于ruby - 可能对 curry 过程进行 instance_eval 吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24533728/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com