ruby中块中定义的常量的常量定义的上下文是什么?
这里有个问题可以迷惑你的面条 在使用类作为接收器的ruby中块中定义的常量的常量定义的上下文是什么?,ruby,metaprogramming,Ruby,Metaprogramming,这里有个问题可以迷惑你的面条 在使用类作为接收器的class\u eval计算的块中,方法声明和常量声明之间似乎存在差异。下面的一些代码演示了这种差异: module X def save_block(&block) @block = block end end module Y extend X save_block do SOME_CONSTANT = 1 def meth "a method" end end d
class\u eval
计算的块中,方法声明和常量声明之间似乎存在差异。下面的一些代码演示了这种差异:
module X
def save_block(&block)
@block = block
end
end
module Y
extend X
save_block do
SOME_CONSTANT = 1
def meth
"a method"
end
end
def self.included(m)
m.class_eval &@block
end
end
class Z
include Y
end
class W
include Y
end
至少在Ruby 1.9.3中执行此代码会导致以下错误:
warning: already initialized constant SOME_CONSTANT
我没想到。首先考虑<代码> METH < /C> >:
Z.instance_methods(false)
=> [:meth]
W.instance_methods(false)
=> [:meth]
并且Y
没有任何实例方法:
Y.instance_methods(false)
=> []
这是有意义的,因为块是以Z
和W
作为class\u eval
的接收者执行的。但是,常数不同,因此会显示错误消息,如下所示:
Y.constants(false)
=> [:SOME_CONSTANT]
Z.constants(false)
=> []
W.constants(false)
=> []
在这里,常量最终在Y
中定义(出于某种奇怪的原因),因此当第二次执行块时,常量some_常量
已经定义
我非常期待得到一些启示
更新(2012/11/19):
正如@phoet在下面指出的(对我对他的回答的评论的回应),常量是在块的范围内定义的,也就是说,在块最初定义的范围内。在我的示例中,这将是Y。如本问题所述,常量处理在它的“词汇范围”内,这意味着它们定义的上下文,而不是它们执行的上下文。常量肯定不是在并行时间创建的。例如,如果我在定义Z或W之前执行
Y.constants(false)
,但在定义Y之后执行,则会得到空数组[]
。必须为要定义的常量计算块。我只是不知道为什么常数分别附着在Y而不是Z和W上。是的,你是对的。这是关于范围界定的:如果你更新你的答案,为了反映这一点,我会接受它(我已经在我的原始问题中添加了注释)。