长话短说:
(object = Object.new).instance_eval &block
集:
Object.class_eval &block
集:
self
到Object
- “当前级” 到
Object
“当前级” 被用于def
,undef
和alias
,以及常数和类变量查找。
现在,让我们来看一下实现细节。
下面是如何module_eval
和instance_eval
用C实现:
VALUE rb_mod_module_eval(int argc, VALUE *argv, VALUE mod) {
return specific_eval(argc, argv, mod, mod);
}
VALUE rb_obj_instance_eval(int argc, VALUE *argv, VALUE self) {
VALUE klass;
if (SPECIAL_CONST_P(self)) { klass = Qnil; }
else { klass = rb_singleton_class(self); }
return specific_eval(argc, argv, klass, self);
}
两个呼叫specific_eval
,它采用下列参数:int argc
,VALUE *argv
,VALUE klass
和VALUE self
。
注意的是:
module_eval
经过Module
或Class
实例作为既klass
和self
instance_eval
传递对象的singleton类作为klass
如果给定的块,specific_eval
将呼叫yield_under
,其中采用以下参数:VALUE under
,VALUE self
和VALUE values
。
if (rb_block_given_p()) {
rb_check_arity(argc, 0, 0);
return yield_under(klass, self, Qundef);
}
有在yield_under
两个重要行:
block.self = self;
此设置块到接收器的self
。
cref = vm_cref_push(th, under, NOEX_PUBLIC, blockptr);
的cref
是链表 指定的“当前级”,其用于def
,undef
和alias
,以及 恒定和类变量查找。
该行基本上将cref
设置为under
。
最后:
有一两件事:内'class_eval'分配常量和类变量不起作用它在类定义的方式/重启:它使用外部范围。 – Alexey 2012-04-24 21:19:34
@Alexey,你是对的。我敢打赌,这与'NODE_FL_CREF_PUSHED_BY_EVAL'常数有关。许多方法,例如['Module :: nesting'](http://ruby-doc.org/core-1.9.3/Module.html#method-c-nesting),似乎忽略了一个'cref'节点如果标志被设置。 – 2012-04-24 22:38:06