Область действия изменена для процедуры, которая затем оценивается в этом контексте. Внутри все процессы хранятся в памяти как C struct
, который включает self
процедуры (область, в которой был сделан процесс) Когда вы вызываете instance_eval
, значение self
вручную изменяется в памяти на объект, для которого вы вызываете instance_eval
. Если вы изучите исходный код ruby, вы обнаружите, что он сводится к этой функции:
static VALUE
yield_under(VALUE under, VALUE self, VALUE values)
{
rb_thread_t *th = GET_THREAD();
rb_block_t block, *blockptr;
NODE *cref;
if ((blockptr = GC_GUARDED_PTR_REF(th->cfp->lfp[0])) != 0) {
block = *blockptr;
block.self = self; // <- This is where the scope changes!
th->cfp->lfp[0] = GC_GUARDED_PTR(&block);
}
cref = vm_cref_push(th, under, NOEX_PUBLIC, blockptr);
cref->flags |= NODE_FL_CREF_PUSHED_BY_EVAL;
if (values == Qundef) {
return vm_yield_with_cref(th, 1, &self, cref);
}
else {
return vm_yield_with_cref(th, RARRAY_LENINT(values), RARRAY_PTR(values), cref);
}
}
Обратите внимание на строку, содержащую // <- This is where the scope changes!
.