问题 Ruby Koan:常数成为符号


在about_symbols.rb Ruby Koan(https://github.com/edgecase/ruby_koans)中,我有以下代码:

    RubyConstant = "What is the sound of one hand clapping?"
    def test_constants_become_symbols
      all_symbols = Symbol.all_symbols

      assert_equal true, all_symbols.include?(:"nonexistent")

      assert_equal true, all_symbols.include?(:"What is the sound of one hand clapping?")
      assert_equal true, all_symbols.include?("What is the sound of one hand clapping?".to_sym)
    end

按原样,测试通过。

三个问题:

  1. 为什么第一个断言通过? :"nonexistent" 不应该包括在all_symbols中,但它包含在内,所以我必须误解一些东西。

  2. 当我注释掉第二个断言时,测试失败是因为 "What is the sound of one hand clapping?".to_sym 不包括在all_symbols中 :"What is the sound of one hand clapping?" 已经包括了。既然它们是等价的,为什么最后一个断言失败了?另外,为什么第二个断言未被注释时它会通过? (为什么第二个断言对第三个断言有影响?)

  3. 据我所知,这个Ruby Koan的观点是证明常量成为符号(至少,这是我从方法名称推断的)。由于RubyConstant是具有值的常量 "What is the sound of one hand clapping?",为什么不呢 "What is the sound of one hand clapping?".to_sym 包含在符号列表中?我能想到的唯一解释是,与方法名称相反,常量实际上不会成为符号。

谢谢你的帮助!


12757
2018-03-18 23:16


起源

这里问同样的问题:stackoverflow.com/questions/13295776/... - ZenBalance


答案:


hoha说的没错,但我会尝试扩展并澄清一下。

口译员将创建 :nonexistent 解析时的符号 test_constants_become_symbols。然后,当你运行它, Symbol.all_symbols 被调用来获取所有已知符号的列表 :nonexistent 在列表中。另请注意双引号 "nonexistent" 是语法问题而不是内部表示问题 :nonexistent 和 :"nonexistent" 是一回事。

如果你注释掉这个:

  assert_equal true, all_symbols.include?(:"What is the sound of one hand clapping?")

那么 :"What is the sound of one hand clapping?" 解析器不会看到符号,因此它不会出现在 all_symbols 阵列。该 .to_sym 当执行以下行时的方法调用 test_constants_become_symbols 执行;所以 :"What is the sound of one hand clapping?" 获得你的符号后创建符号 all_symbols 这将失败:

  assert_equal true, all_symbols.include?("What is the sound of one hand clapping?".to_sym)

如果你执行 test_constants_become_symbols 再次在同一个解释器实例中(第二个 assert_equal 仍然评论出来)然后两个都没有评论 assert_equal 调用将在第一次运行时通过 test_constants_become_symbols 将创造 :"What is the sound of one hand clapping?" 第二个 Symbol.all_symbols 将它包含在返回的数组中。

运行代码 irb 没有包装它 def 可能会帮助你了解发生了什么。


7
2018-03-18 23:43



据我所知,这个Ruby Koan的观点是证明常量成为符号(至少,这是我从方法名称推断的)。因为声明了RubyConstant,为什么不是 "What is the sound of one hand clapping?".to_sym 包含在符号列表中?我能想到的唯一解释是,与方法名称相反,常量实际上不会成为符号。有什么想法吗? - dskang
它不是变为符号的常数的值。它是常数的名称。所以 Symbol.all_symbols.include? :RubyConstant 是真的。 - Harry Steinhilber
该 名称 常数变成了符号,但不是 值 常数。尝试这个: Zoo="Zee"; p Symbol.all_symbols.grep(/^Z/) #=> [:ZeroDivisionError, :Zoo] - Phrogz
谢谢!现在有意义了。 - dskang
@ZenBalance:我认为这取决于什么时候 Symbol.all_symbols 和 RubyConstant.to_sym 被评估。如果 to_sym 首先是 all_symbols 将包括它,否则它可能不在那里。 - mu is too short


我不是Ruby大师,但看起来解释器在这期间创建了这个符号 def 表达评价。这就是为什么当你打电话时这些符号已经存在的原因 Symbol.all_symbols。第三 assert 失败,第二个被注释掉,因为 "string".to_sym 在方法执行期间创建符号,即在获得可用符号之后 all_symbols = Symbol.all_symbols


3
2018-03-18 23:22