Ruby Koans: ¿Por qué convertir la lista de símbolos en cadenas?

Me refiero a esta prueba en about_symbols.rb en Ruby Koans https://github.com/edgecase/ruby_koans/blob/master/src/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? 

¿Por qué exactamente tenemos que convertir esa lista en cadenas primero?

Esto tiene que ver con cómo funcionan los símbolos. Para cada símbolo, solo uno de ellos existe realmente. Detrás de las escenas, un símbolo es solo un número al que se hace referencia por un nombre (que comienza con dos puntos). Por lo tanto, al comparar la igualdad de dos símbolos, estás comparando la identidad del objeto y no el contenido del identificador que se refiere a este símbolo.

Si hicieras la prueba simple : prueba == “prueba” , será falso. Por lo tanto, si tuviera que reunir todos los símbolos definidos hasta ahora en una matriz, primero tendría que convertirlos en cadenas antes de compararlos. No puede hacer esto de la manera opuesta (primero convierta la cadena que desea comparar en un símbolo), ya que crearía la única instancia de ese símbolo y “contaminaría” su lista con el símbolo que está probando para ver si existe.

Espero que ayude. Esto es un tanto extraño, ya que tiene que probar la presencia de un símbolo sin crearlo accidentalmente durante la prueba. Por lo general, no ves código como ese.

Porque si lo haces

 assert_equal true, all_symbols.include?(:test_method_names_become_symbols) 

puede (dependiendo de su implementación de ruby) automáticamente ser cierto, porque al preguntar sobre :test_method_names_become_symbols crea. Ver este informe de error .

Ambas respuestas anteriores son correctas, pero a la luz de la pregunta de Karthik anterior, pensé que publicaría una prueba que ilustra cómo se podría pasar un símbolo con precisión al método de 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 

Una nota adicional sobre los Koans: haga uso de las declaraciones de put y las pruebas personalizadas si no entiende nada. Por ejemplo, si ves:

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

y no tienen idea de lo words podrían ser las words , agregue la línea

 puts words 

y ejecuta rake en la línea de comandos. Del mismo modo, pruebas como la que agregué anteriormente pueden ser útiles para entender algunos de los matices de Ruby.