【问题标题】:Fetch dynamically a defined constant动态获取定义的常量
【发布时间】:2020-03-13 07:42:24
【问题描述】:

根据 Ruby const_get 的文档,此方法返回一个常量的值。

所以要重现以下行为:

module A
  FOO = 42

  module B
    def self.call
      FOO
    end
  end
end

A::B.call # => 42

我写了这段代码:

A = Module.new
A.const_set(:FOO, 42)
A.const_set(:B, Module.new do
  def self.call
    const_get(:FOO)
  end
end)

但是当我调用该方法时,我有一个NameError 异常:

A::B.call # => exception
# NameError (uninitialized constant A::B::FOO)
# Did you mean?  A::FOO

看起来FOOconst_get(:FOO) 并不完全相同。

还有其他方法可以在父模块中递归查找FOO 常量吗?

编辑:

const_get 直接做我也有这个问题:

module A
  FOO = 42

  module B
    def self.a_method
      const_get(:FOO)
    end
  end
end

A::B.a_method # => exception
# NameError (uninitialized constant A::B::FOO)
# Did you mean?  A::FOO

【问题讨论】:

  • article on constant lookup。顺便说一句,如果没有问题,使用与核心方法名称相同的方法名称(此处为call)会令人困惑。
  • module A 内部定义module B 实际上与直接定义module A::B 不同。包装意味着当您以其他方式执行时不存在的搜索范围。
  • 我同意@tadman 的评论,并且我添加了另一个示例以确保代码是ISO 与工作FOO 之一。唯一的区别是,我将FOO 替换为const_get(:FOO)。它不再起作用。所以我认为麻烦来自const_get方法IMO。

标签: ruby metaprogramming


【解决方案1】:

我们可以使用Module::nesting的方法来更好地理解这里发生了什么。

module A
  FOO = 42
  module B
    puts "Module.nesting = #{Module.nesting}"
    def self.call
      FOO
    end
  end
end

展示

Module.nesting = [A::B, A]

这告诉我们,在执行A::B.call 时,在搜索FOO 的值时,Ruby 首先在模块A::B 中查找,没有找到它,然后在模块A 中找到它.

您的第三个代码片段还创建了一个嵌套模块A::B

module A
  FOO = 42
  module B
    puts "Module.nesting = #{Module.nesting}"
    def self.a_method
      const_get(:FOO)
    end
  end
end

展示

Module.nesting = [A::B, A]

A::B.a_method 执行 A::B.const_get(:FOO)Module#const_get 的文档指出,“在 mod 中检查具有给定名称的常量。”因此,如果它未能在作为其接收者的模块中找到常量,它会放弃而不检查给定模块嵌套在其中的任何模块。

您的第二个代码片段与第三个类似,因为const_get 的行为,它无法找到FOO 的值。

【讨论】:

  • 你的解释我理解得更好。但是,如何(在纯元编程中)我可以创建一个带有常量和子模块的模块,并通过类方法获取常量?不可能吗?
  • 我不确定我是否遵循。如果module A; FOO = 1; module B; def self.b; "FOO=#{FOO}"; end; end; endA::B.b #=> "FOO=1"。你是这个意思吗?当我写作时,我的狗正在拉我的裤腿,告诉我该散步了。我稍后再检查。
猜你喜欢
  • 2011-05-14
  • 2013-04-08
  • 2017-07-07
  • 1970-01-01
  • 2015-01-27
  • 2013-09-16
  • 2013-03-20
  • 2011-09-03
相关资源
最近更新 更多