Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/ruby/23.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
ruby中块中定义的常量的常量定义的上下文是什么?_Ruby_Metaprogramming - Fatal编程技术网

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上。是的,你是对的。这是关于范围界定的:如果你更新你的答案,为了反映这一点,我会接受它(我已经在我的原始问题中添加了注释)。