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
按原样,测试通过。
三个问题:
-
为什么第一个断言通过?
:"nonexistent"
不应该包括在all_symbols中,但它包括在内,所以我必须误解一些东西。 -
当我注释掉第二个断言时,测试失败了,因为
"What is the sound of one hand clapping?".to_sym
不包含在all_symbols中,而是:"What is the sound of one hand clapping?"
已经包括了。 既然它们是等价的,为什么最后一个断言失败了? 另外,为什么第二个断言未被注释时它会通过? (为什么第二个断言对第三个断言有影响?) -
据我所知,这个Ruby Koan的观点是certificate常量成为符号(至少,这是我从方法名称推断的)。 因为RubyConstant是一个常数,其值为
"What is the sound of one hand clapping?"
,为什么不是"What is the sound of one hand clapping?".to_sym
包含在符号列表中? 我能想到的唯一解释是,与方法名称相反,常量实际上不会成为符号。
谢谢你的帮助!
hoha说的没错,但我会尝试扩展并澄清一下。
解析器在解析test_constants_become_symbols
时将创建:nonexistent
符号。 然后,当您运行它时,将调用Symbol.all_symbols
以获取所有已知符号的列表,并且:nonexistent
列表中: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
数组中。 执行test_constants_become_symbols
,执行以下行上的.to_sym
方法调用; 所以, :"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大师,但看起来解释器在def
表达式评估期间创建了这个符号。 这就是当你调用Symbol.all_symbols
时这些符号已经存在的原因。 第三个assert
失败,第二个被注释掉,因为"string".to_sym
在方法执行期间创建符号,即在获得带有all_symbols = Symbol.all_symbols
符号all_symbols = Symbol.all_symbols
。