Подтвердить что ты не робот

Ruby Koans: зачем конвертировать список символов в строки?

Я имею в виду этот тест в about_symbols.rb в Ruby Koans https://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?

Почему именно нам нужно сначала преобразовать этот список в строки?

4b9b3361

Ответ 1

Это связано с тем, как работают символы. Для каждого символа фактически существует только один из них. За кулисами символ - это просто номер, называемый именем (начиная с двоеточия). Таким образом, при сравнении равенства двух символов вы сравниваете идентификацию объекта, а не содержимое идентификатора, относящегося к этому символу.

Если вам нужно выполнить простой тест : test == "test" , он будет ложным. Итак, если вы собрали все символы, определенные до сих пор в массив, вам нужно будет сначала преобразовать их в строки, прежде чем сравнивать их. Вы не можете сделать это противоположным образом (сначала преобразуйте строку, которую хотите сравнить, в символ), потому что это создаст единый экземпляр этого символа и "загрязнит" ваш список символом, который вы тестируете для существования.

Надеюсь, что это поможет. Это немного странно, потому что вам нужно проверить наличие символа, не случайно создавая этот символ во время теста. Обычно вы не видите такой код.

Ответ 2

Потому что, если вы делаете

assert_equal true, all_symbols.include?(:test_method_names_become_symbols)

он может (в зависимости от вашей реализации ruby) автоматически быть правдой, потому что запрос о :test_method_names_become_symbols создает его. См. этот отчет об ошибках.

Ответ 3

Оба вышеперечисленные ответы верны, но в свете вопроса Karthik выше я думал, что отправлю тест, который иллюстрирует, как можно точно передать символ методу 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, а также пользовательские тесты, если вы ничего не понимаете. Например, если вы видите:

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

и не знаю, что может быть words, добавьте строку

puts words

и запустите rake в командной строке. Аналогично, тесты, подобные тому, который я добавил выше, могут быть полезны с точки зрения понимания некоторых нюансов Ruby.