Para resumir:
(object = Object.new).instance_eval &block
conjuntos:
Object.class_eval &block
conjuntos:
self
-Object
- La "clase actual" para
Object
La "clase actual" se utiliza para def
, undef
y alias
, así como operaciones de búsqueda variables constantes y de clase.
Ahora, echemos un vistazo a los detalles de implementación.
Así es como module_eval
y instance_eval
se implementan en 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);
}
Tanto llamada specific_eval
, que tiene los siguientes argumentos: int argc
, VALUE *argv
, VALUE klass
y VALUE self
.
en cuenta que:
module_eval
pasa la instancia Module
o Class
como tanto klass
yself
instance_eval
pasa clase singleton del objeto como klass
Si se les da un bloque , specific_eval
llamará al yield_under
, que toma los siguientes argumentos: VALUE under
, VALUE self
y VALUE values
.
if (rb_block_given_p()) {
rb_check_arity(argc, 0, 0);
return yield_under(klass, self, Qundef);
}
Hay dos líneas importantes en yield_under
:
block.self = self;
Esto establece el self
del bloque para el receptor.
cref = vm_cref_push(th, under, NOEX_PUBLIC, blockptr);
El cref
es una lista vinculado que especifica la "clase actual", que se utiliza para def
, undef
y alias
, así búsquedas de variables como constantes y de clase.
Esa línea básicamente establece cref
en under
.
Por último:
cuando se llama desde module_eval
, under
será el Class
o Module
ejemplo.
Cuando se llama desde instance_eval
, under
será la clase Singleton de self
.
hay una cosa: en el interior 'class_eval' asignar constantes y variables de clase no funciona de la forma en que funciona en la definición de la clase/reapertura: se usa el alcance externo. – Alexey
@Alexey, tienes razón. Apuesto a que tiene algo que ver con la constante 'NODE_FL_CREF_PUSHED_BY_EVAL'. Muchos métodos, como ['Module :: nesting'] (http://ruby-doc.org/core-1.9.3/Module.html#method-c-nesting) por ejemplo, parecen ignorar un nodo' cref' si la bandera está configurada –