【问题标题】:Ruby Koan: Constants become symbolsRuby Koan:常量成为符号
【发布时间】:2011-07-18 12:58:36
【问题描述】:

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

感谢您的帮助!

【问题讨论】:

标签: ruby symbols


【解决方案1】:

hoha 说得对,但我会尝试扩展和澄清一下。

解释器在解析test_constants_become_symbols 时将创建:nonexistent 符号。然后,当您运行它时,会调用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 中可能会帮助您了解发生了什么。

【讨论】:

  • 据我所知,这个 Ruby Koan 的重点是证明常量变成了符号(至少,这是我从方法名称中推断出来的)。既然声明了 RubyConstant,为什么"What is the sound of one hand clapping?".to_sym 不包含在符号列表中?我能想到的唯一解释是,与方法名称相反,常量实际上并没有成为符号。有什么想法吗?
  • 不是常量的值成为符号。它是常量的名称。所以Symbol.all_symbols.include? :RubyConstant 是真的。
  • 常量的name变成了一个符号,而不是常量的value。试试这个:Zoo="Zee"; p Symbol.all_symbols.grep(/^Z/) #=> [:ZeroDivisionError, :Zoo]
  • @HarrySteinhilber 的评论就是答案
  • @ZenBalance:我认为这取决于何时评估 Symbol.all_symbolsRubyConstant.to_sym。如果to_sym 先出现,那么all_symbols 将包含它,否则它可能不存在。
【解决方案2】:

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-04-13
    • 1970-01-01
    • 2015-03-11
    • 1970-01-01
    • 1970-01-01
    • 2011-03-25
    • 2013-11-15
    • 1970-01-01
    相关资源
    最近更新 更多