- xml - AJAX/Jquery XML 解析
- 具有多重继承的 XML 模式
- .net - 枚举序列化 Json 与 XML
- XML 简单类型、简单内容、复杂类型、复杂内容
我在尝试回答 this 时想到了这个问题.以下是预期的行为:
module A
p Module.nesting
end
# => [A]
但是以下内容:
A.instance_eval{p Module.nesting}
A.instance_exec{p Module.nesting}
A.module_eval{p Module.nesting}
A.module_exec{p Module.nesting}
全部返回[]
。为什么这些不能像上面那样工作?
附加问题
Mu is too short 提出了一个有趣的观点。如果这是正确的,那么 Module.nesting
将是依赖于文字上下文的方法和变量之一,例如 Method#source_location
、__FILE__
。这种理解是否正确?如果是这样,有人可以提供这些依赖于文字上下文的方法/变量的 list 吗?我认为这对引用很有用。
最佳答案
警告:这有点长而且杂乱无章。由于文档有点薄,因此似乎有必要浏览一下 Ruby 源代码。如果您不关心香肠是如何制作的,请随意跳到最后。
1.9.2 Module.nesting
在 eval.c
中实现像这样:
static VALUE
rb_mod_nesting(void)
{
VALUE ary = rb_ary_new();
const NODE *cref = rb_vm_cref();
while (cref && cref->nd_next) {
VALUE klass = cref->nd_clss;
if (!(cref->flags & NODE_FL_CREF_PUSHED_BY_EVAL) &&
!NIL_P(klass)) {
rb_ary_push(ary, klass);
}
cref = cref->nd_next;
}
return ary;
}
我不太了解 Ruby 内部原理,但我阅读了 while
像这样循环:从 cref
中提取链接列表所有与类似类的事物关联但不是来自 eval
的节点. NODE_FL_CREF_PUSHED_BY_EVAL
位仅在此处设置:
/* block eval under the class/module context */
static VALUE
yield_under(VALUE under, VALUE self, VALUE values)
更多的 grepping 和阅读表明 instance_eval
最终会通过 yield_under
.我会离开检查 instance_exec
, module_eval
, 和 module_exec
作为读者的练习。无论如何,它看起来像 instance_eval
明确排除在 Module.nesting
之外列表;然而,这比其他任何事情都更让人分心,它只是意味着您不会看到 evals 提到的内容。
所以现在的问题是“NODE
和 rb_vm_cref()
到底是什么?”。
如果您查看 node.h
您会看到一堆用于各种 Ruby 关键字和语言结构的 NODE 常量:
NODE_BLOCK
NODE_BREAK
NODE_CLASS
NODE_MODULE
NODE_DSYM
所以我猜 NODE
是指令树中的一个节点。这很符合我的
Module.nesting
seems to be more about talking to the parser
评论中的猜想。但无论如何我们都会继续前进。
rb_vm_cref
函数只是 vm_get_cref
的包装器这是 vm_get_cref0
的包装器.什么是 vm_get_cref0
所有关于?都是关于这个的:
static NODE *
vm_get_cref0(const rb_iseq_t *iseq, const VALUE *lfp, const VALUE *dfp)
{
while (1) {
if (lfp == dfp) {
return iseq->cref_stack;
}
else if (dfp[-1] != Qnil) {
return (NODE *)dfp[-1];
}
dfp = GET_PREV_DFP(dfp);
}
}
函数的所有三个参数都直接来自这个控制框架:
rb_control_frame_t *cfp = rb_vm_get_ruby_level_next_cfp(th, th->cfp);
iseq
似乎是一个指令序列和 lfp
和 dfp
是帧指针:
VALUE *lfp; // cfp[6], local frame pointer
VALUE *dfp; // cfp[7], dynamic frame pointer
cref_stack
的定义是相关的:
/* klass/module nest information stack (cref) */
NODE *cref_stack;
所以看起来您正在从 rb_vm_cref
中获得某种调用或嵌套堆栈.
现在回到手头的细节。当您这样做时:
module A
p Module.nesting
end
你会得到 module A
在cref
链接列表(过滤后生成 Module.nesting
结果数组),因为您没有点击 end
然而。当你说这些时:
A.instance_eval { puts Module.nesting }
A.instance_exec { puts Module.nesting }
A.module_eval { puts Module.nesting }
A.module_exec { puts Module.nesting }
你不会有 module A
在cref
不再是因为您已经点击了 end
弹出module A
离开堆栈。但是,如果您这样做:
module A
instance_eval { puts Module.nesting.inspect }
instance_exec { puts Module.nesting.inspect }
module_eval { puts Module.nesting.inspect }
module_exec { puts Module.nesting.inspect }
end
你会看到这个输出:
[A]
[A]
[A]
[A]
因为 module A
尚未关闭(并弹出 cref
)。
最后, Module.nesting
documentation是这样说的:
Returns the list of Modules nested at the point of call.
我认为这个声明结合内部审查表明Module.nesting
实际上取决于调用它的特定文字上下文。
如果任何在 Ruby 内部有更多经验的人有什么要补充的,我可以将其作为社区 wiki 交给 SO 社区。
更新:所有这些都适用于 class_eval
以及它对 module_eval
的影响它也适用于 1.9.3 和 1.9.2。
关于ruby - 模块嵌套在 instance_eval/exec 或 module_eval/exec 中,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6337821/
我有以下代码: class A def self.scope yield end def self.method_added method self.instance_ev
我对 instance_eval 的理解是,如果我有模块 M,那么以下是等价的: module M def foo :foo end end class C class true
单例方法是一种只在一个实例上定义的方法。 foo = Foo.new def foo.case #singleton method end instance_eval 不是做同样的事情吗?为特定实
我正在尝试一些 ruby 元编程,但对 instance_eval() 感到有些困惑。 看下面的例子 @instance_var = 'instance_var' local_var = 'loc
虽然我已经使用了一段时间,但我似乎对这两种方法感到困惑,我无法理解为什么方法 passengers 没有被添加到以下代码中的对象中: class Bus def number_of_seats
看着这个instance_eval示例: class KlassWithSecret def initialize @secret = 99 end def g
我正在尝试调用对象 foo 的方法,就好像它是对象 bar 的方法一样。我尝试了两种方法: 1。解除绑定(bind)和绑定(bind) - 由于类不同而失败 class Foo def initi
当我在 instance_eval block 中为类定义一个方法时,它会创建一个很好的类方法。 例如) class A end A.instance_eval do def method; en
我想对 DSL 进行一些改进。我能够使用此示例进行改进: module ArrayExtras refine Array do def speak puts 'array!'
Foo = Class.new Foo.instance_eval do def instance_bar "instance_bar" end end puts Foo.instan
class_eval 有什么区别吗? & instance_eval工作除了def ?里面class_eval block def定义类自身的方法(即实例方法)和内部 instance_eval de
我发现传递给 class_eval、module_eval 和 instance_eval 的行号与错误报告的行号不匹配。 ruby-doc 未解释此行为其中说:(以 instance_eval 为例
伙计们。我创建了一个类: class A def initialize &b instance_eval &b end def method_missing method_id,
完整代码:http://friendpaste.com/5TdtGPZaEK0DbDBa2DCUyB class Options def method_missing(method, *arg
我正在研究 Pickaxe 1.9,我对 instance/class_eval block 中的常量查找感到有点困惑。我正在使用 1.9.2。 似乎 Ruby 在 *_eval block 中处理常
我了解 instance_eval 和 class_eval 之间的基本区别。我在玩弄时发现的是一些涉及 attr_accessor 的奇怪东西。这是一个例子: A = Class.new A.cla
class Foo include Module.new { class_eval "def lab; puts 'm' end" } def lab super
我知道 send 接受带有参数的字符串或符号,而 instance_eval 接受字符串或 block ,并且它们的区别在给定接收者时可能很明显。 我的问题是下面示例的“幕后”区别是什么? 1234.
如果我这样做 def eval_file(file) instance_eval read(file) end 然后,一旦文件内的方法/ block 之一发生某些事情,我所看到的就是“eval_f
我最近尝试做类似的事情: a = "some string" b = Proc.new{ upcase } a.instance_eval b 这给出了错误: TypeError: can't con
我是一名优秀的程序员,十分优秀!