長話短說:
(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