Ruby Koan:常量成为符号

时间:2011-03-18 23:16:13

标签: ruby symbols

在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不包含在符号列表中?我能想到的唯一解释是,与方法名称相反,常量实际上不会成为符号。

  4. 感谢您的帮助!

2 个答案:

答案 0 :(得分:7)

霍哈说得对,但我会尝试扩大和澄清一点。

解释器在解析: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调用将在第一次通过{{1}时通过}将创建test_constants_become_symbols,第二个:"What is the sound of one hand clapping?"将其包含在返回的数组中。

Symbol.all_symbols中运行代码而不将其包装在irb中可能有助于您了解正在发生的事情。

答案 1 :(得分:3)

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