[英]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_c
在vm.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.