Proc.new
如果在一个附加了一个的方法内没有一个调用,将使用该方法的块。这是记录在案的行为。
要了解 YARV 是如何做到的,让我们阅读源代码。具体来说,proc_new
函数:
block_pointer = rb_vm_control_frame_block_ptr(control_frame_pointer);
此行检索指向与当前控制帧关联的块的指针。
我相信这些控制框架实现了 Ruby 的堆栈。我们目前在Proc.new
控制框架内,因此这将检索指向该方法的块的指针。
if (block_pointer != NULL) {
/* block found */
} else {
/* block not found... */
}
如果指针不是NULL
,则Proc.new
显式传递了一个块。但是,如果指针是 NULL
怎么办?
/* block not found... */
control_frame_pointer = RUBY_VM_PREVIOUS_CONTROL_FRAME(control_frame_pointer);
block_pointer = rb_vm_control_frame_block_ptr(control_frame_pointer);
我们在堆栈上向上移动并尝试获取它的块。换句话说,我们向上移动到调用者的控制框架并尝试获取它的块。
if (block_pointer != NULL) {
if (is_lambda) {
rb_warn("tried to create Proc object without a block");
}
} else {
rb_raise(rb_eArgError, "tried to create Proc object without a block");
}
现在,如果不是NULL
,那么我们就成功了。如果它仍然是 NULL
,那么我们无法创建Proc
,所以我们提出了ArgumentError
。
该算法归结为:
- 看看是否
Proc.new
给了一个块
- 如果是这样,请使用它
- 如果没有,请查看是否给调用者一个块
- 如果是这样,请使用它
- 如果不是,则引发错误
为提高可读性而更改了源代码。访问 GitHub 上的链接源文件以获取原始文件。