Ruby Koans:为什么要将符号列表转换为string

我在ruby Koans的about_symbols.rb中提到这个testinghttps://github.com/edgecase/ruby_koans/blob/master/koans/about_symbols.rb#L26

def test_method_names_become_symbols symbols_as_strings = Symbol.all_symbols.map { |x| x.to_s } assert_equal true, symbols_as_strings.include?("test_method_names_become_symbols") end # THINK ABOUT IT: # # Why do we convert the list of symbols to strings and then compare # against the string value rather than against symbols? 

为什么我们必须首先将该列表转换为string?

这与符号如何工作有关。 对于每个符号,只有一个实际存在。 在幕后,一个符号只是一个由名字引用的数字(以冒号开头)。 因此,在比较两个符号的相等性时,比较对象的身份而不是引用这个符号的标识符的内容。

如果你要做简单的testing:test ==“test” ,那将是错误的。 因此,如果您要将迄今为止定义的所有符号都收集到一个数组中,则在比较它们之前,需要先将它们转换为string。 你不能以相反的方式做到这一点(首先将要比较的string转换为符号),因为这样做会创build该符号的单个实例,并使用正在testing的符号“污染”列表。

希望有所帮助。 这有点奇怪,因为在testing过程中,您必须testing符号的存在,而不会意外创build该符号。 你通常不会看到这样的代码。

因为如果你这样做

 assert_equal true, all_symbols.include?(:test_method_names_become_symbols) 

它可能(取决于你的ruby实现)自动为true,因为询问:test_method_names_become_symbols创build它。 看到这个错误报告 。

上述两个答案都是正确的,但是鉴于上面的Karthik的问题,我想我会发布一个testing,说明如何准确地将一个符号传递给include方法

 def test_you_create_a_new_symbol_in_the_test array_of_symbols = [] array_of_symbols << Symbol.all_symbols all_symbols = Symbol.all_symbols.map {|x| x} assert_equal false, array_of_symbols.include?(:this_should_not_be_in_the_symbols_collection) #this works because we stored all symbols in an array before creating the symbol :this_should_not_be_in_the_symbols_collection in the test assert_equal true, all_symbols.include?(:this_also_should_not_be_in_the_symbols_collection) #This is the case noted in previous answers...here we've created a new symbol (:this_also_should_not_be_in_the_symbols_collection) in the test and then mapped all the symbols for comparison. Since we created the symbol before querying all_symbols, this test passes. end 

关于Koans的补充说明:如果你什么都不懂,可以使用puts语句和自定义testing。 例如,如果您看到:

 string = "the:rain:in:spain" words = string.split(/:/) 

并不知道可能是什么words ,加上这一行

 puts words 

并在命令行运行rake 。 同样,像上面添加的那样的testing可以帮助理解Ruby的一些细微差别。