让我们来看看常量赋值如何在内部工作。下面的代码是从ruby-1.9.3-p0的源代码tarball中提取的。首先我们来看看虚拟机指令setconstant
(这是用来分配常数)的定义:
# /insns.def, line 239
DEFINE_INSN
setconstant
(ID id)
(VALUE val, VALUE cbase)
()
{
vm_check_if_namespace(cbase);
rb_const_set(cbase, id, val);
INC_VM_STATE_VERSION();
}
没有机会把钩在vm_check_if_namespace
或INC_VM_STATE_VERSION
这里。所以,我们看rb_const_set
(variable.c:1886年),被称为每次恒定分配的功能:
# /variable.c, line 1886
void
rb_const_set(VALUE klass, ID id, VALUE val)
{
rb_const_entry_t *ce;
VALUE visibility = CONST_PUBLIC;
# ...
check_before_mod_set(klass, id, val, "constant");
if (!RCLASS_CONST_TBL(klass)) {
RCLASS_CONST_TBL(klass) = st_init_numtable();
}
else {
# [snip], won't be called on first assignment
}
rb_vm_change_state();
ce = ALLOC(rb_const_entry_t);
ce->flag = (rb_const_flag_t)visibility;
ce->value = val;
st_insert(RCLASS_CONST_TBL(klass), (st_data_t)id, (st_data_t)ce);
}
我删除了所有甚至没有所谓的第一次恒定分配的代码在模块内部。然后,我查看了这个函数调用的所有函数,但没有找到可以从Ruby代码放置钩子的单个点。这意味着难以理解的是,除非我遗漏了某些东西,否则将会有一种挂钩常量分配的方式(至少在MRI中)。
更新
澄清:匿名类不不神奇尽快得到一个新的名字,因为它被分配(如安德鲁的回答正确地指出)。相反,常量名和类的对象ID存储在Ruby的内部常量查找表中。如果在此之后请求了课程名称,现在可以解析为专有名称(而不仅仅是Class:0xXXXXXXXX...
)。
因此,对此作业做出最好的反应是在背景工作线程的循环中检查类的name
,直到它不是nil
(这是一个巨大的资源浪费,恕我直言)。
非常有趣的问题。 – 2012-01-02 20:36:29
AFAIK仍然没有变量赋值,常量或其他方法([很长一段时间在这里看到相同的问题](http://www.ruby-forum.com/topic/65720))。全局,是的。 – 2012-01-02 21:14:56