99 votes

Ruby Koans: Pourquoi convertir une liste de symboles en chaînes

Je fais référence à ce test dans about_symbols.rb dans 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?
 

Pourquoi exactement devons-nous d'abord convertir cette liste en chaînes?

123voto

AboutRuby Points 4675

Cela a à voir avec la façon dont les symboles de travail. Pour chaque symbole, un seul de il existe réellement. Derrière la scène, un symbole est juste un nombre désignés par un nom (en commençant par un signe deux-points). Ainsi, lorsque l'on compare l'égalité de deux symboles, vous êtes en comparant l'identité de l'objet et non le contenu de l'identifiant qui se réfère à ce symbole.

Si vous décidez de faire le test simple :test == "test", il sera faux. Donc, si vous rassemblez tous les symboles définis jusqu'à présent dans un tableau, vous devez les convertir en chaînes d'abord avant de les comparer. Vous ne pouvez pas le faire dans l'autre sens (de convertir la chaîne de caractères que vous souhaitez comparer un symbole en premier), car le faire serait de créer l'instance unique de ce symbole et de "polluer" votre liste avec le symbole que vous faites des tests pour l'existence.

Espérons que cela aide. C'est un peu bizarre, parce que vous avez à tester la présence d'un symbole en évitant la création de ce symbole lors de l'essai. On ne voit pas souvent de code comme ça.

89voto

Andrew Grimm Points 22996

Parce que si vous faites

 assert_equal true, all_symbols.include?(:test_method_names_become_symbols)
 

il peut (selon votre implémentation de ruby) être automatiquement vrai, car poser des questions sur :test_method_names_become_symbols crée. Voir ce rapport de bogue .

4voto

aceofbassgreg Points 908

Les deux réponses ci-dessus sont correctes, mais à la lumière de Karthik est question ci-dessus, je pensais que j'allais poster un test qui montre comment on peut avec précision passer un symbole de l' include méthode

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

Une note supplémentaire sur les Koans: faire usage de puts des déclarations ainsi que des tests personnalisés si vous ne comprenez pas quelque chose. Par exemple, si vous voyez:

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

et n'ont aucune idée de ce qu' words peut-être, ajouter la ligne

puts words

et exécutez rake à la ligne de commande. De même, des tests comme celui que j'ai ajouté ci-dessus peut être utile dans la compréhension de certaines des nuances Rubis.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X