Ruby Koan:常量成为符号

dsk*_*ang 11 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
Run Code Online (Sandbox Code Playgroud)

按原样,测试通过.

三个问题:

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

谢谢你的帮助!

mu *_*ort 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?")
Run Code Online (Sandbox Code Playgroud)

然后:"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)
Run Code Online (Sandbox Code Playgroud)

如果你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可能会帮助您了解正在发生的事情.

  • 它不是成为符号的常量的值.它是常数的名称.那么`Symbol.all_symbols.include?:RubyConstant`会是真的. (13认同)
  • 常量的_name_变为符号,但不是常量的_value_.试试这个:`Zoo ="Zee"; p Symbol.all_symbols.grep(/ ^ Z /)#=> [:ZeroDivisionError,:Zoo]` (2认同)

hoh*_*oha 5

我不是 Ruby 专家,但看起来解释器在def表达式求值期间创建了这个符号。这就是为什么当您调用 时这些符号已经存在Symbol.all_symbols。第三次assert失败,第二次被注释掉,因为"string".to_sym在方法执行期间创建符号,即在使用 获得可用符号之后all_symbols = Symbol.all_symbols