在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的观点是证明常量成为符号(至少,这是我从方法名称推断的)。由于RubyConstant是具有值的常量 "What is the sound of one hand clapping?"
,为什么不呢 "What is the sound of one hand clapping?".to_sym
包含在符号列表中?我能想到的唯一解释是,与方法名称相反,常量实际上不会成为符号。
谢谢你的帮助!
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
可能会帮助你了解发生了什么。
我不是Ruby大师,但看起来解释器在这期间创建了这个符号 def
表达评价。这就是为什么当你打电话时这些符号已经存在的原因 Symbol.all_symbols
。第三 assert
失败,第二个被注释掉,因为 "string".to_sym
在方法执行期间创建符号,即在获得可用符号之后 all_symbols = Symbol.all_symbols
。