web-dev-qa-db-fra.com

Quel est l'opérateur du colon en Ruby?

Quand je dis { :bla => 1, :bloop => 2 }, que fait exactement le :? J'ai lu quelque part à quel point c'est similaire à une chaîne, mais en quelque sorte à un symbole.

Je ne suis pas très clair sur le concept, quelqu'un pourrait-il m'éclairer?

222
LuxuryMode

:foo est un symbole nommé "foo". Les symboles ont pour caractéristique distincte que deux symboles portant le même nom seront identiques:

"foo".equal? "foo"  # false
:foo.equal? :foo    # true

Cela rend la comparaison de deux symboles très rapide (étant donné que seule une comparaison de pointeur est impliquée, par opposition à la comparaison de tous les caractères comme dans une chaîne), plus vous ne disposerez pas de zillions copies du même symbole.

De plus, contrairement aux chaînes, les symboles sont immuables.

241
Chris Jester-Young

Juste pour démontrer certaines des choses mentionnées dans les réponses:

require 'benchmark'

n = 1_000_000

print '"foo".equal? "foo" -> ', ("foo".equal? "foo"), "\n"
print '"foo" == "foo"     -> ', ("foo" == "foo"    ), "\n"
print ':foo.equal? :foo   -> ', (:foo.equal? :foo  ), "\n"
print ':foo == :foo       -> ', (:foo == :foo      ), "\n"

Benchmark.bm(10) do |b|
  b.report('string')     { n.times { "foo".equal? "foo" }}
  b.report('str == str') { n.times { "foo" == "foo"     }}
  b.report('symbol')     { n.times { :foo.equal? :foo   }}
  b.report('sym == sym') { n.times { :foo == :foo       }}
end

Le lancer en sortie:

"foo".equal? "foo" -> false
"foo" == "foo"     -> true
:foo.equal? :foo   -> true
:foo == :foo       -> true

Ainsi, comparer une chaîne à une chaîne à l'aide de equal? échoue car il s'agit d'objets différents, même s'ils ont un contenu identique. == compare le contenu et les vérifications équivalentes avec des symboles sont beaucoup plus rapides.

                 user     system      total        real
string       0.370000   0.000000   0.370000 (  0.371700)
str == str   0.330000   0.000000   0.330000 (  0.326368)
symbol       0.170000   0.000000   0.170000 (  0.174641)
sym == sym   0.180000   0.000000   0.180000 (  0.179374)

Les deux tests de symbole sont fondamentalement les mêmes en ce qui concerne la vitesse. Après 1 000 000 d'itérations, il n'y a qu'une différence de 0,004733 seconde. Je dirais donc que c'est un lavis entre les deux.

44
the Tin Man

Les symboles permettent de représenter des chaînes et des noms en Ruby.

La principale différence entre les symboles et les chaînes est que les symboles du même nom sont initialisés et n'existent en mémoire qu'une seule fois pendant une session de Ruby.

Ils sont utiles lorsque vous devez utiliser le même mot pour représenter différentes choses.

31
nunopolonia

Il y a quelques citations du célèbre livre Développement Web Agile avec Rails , qui peuvent être utiles pour comprendre également le symbole :

Rails utilise des symboles pour identifier les choses. En particulier, il les utilise comme clés pour nommer les paramètres de méthode et rechercher des éléments dans des hachages.

redirect_to :action => "edit", :id => params[:id]

Vous pouvez considérer les symboles comme des littéraux de chaîne transformés de manière magique en constantes. Alternativement, vous pouvez considérer que les deux points signifient "la chose nommée", ainsi: id est "la chose nommée id".

17
shyan1

Dans Ruby, chaque objet a un identificateur d'objet unique. Si vous écrivez puts "hello".object_id dans votre irb et appuyez sur Entrée pendant 2 heures différentes, vous obtiendrez 2 valeurs renvoyées différentes, mais si vous écrivez :hello.object_id 2 fois vous obtiendrez la même valeur renvoyée. Cela aurait dû expliquer la différence.

4
Devin Huang

Si vous utilisez :foo => bar, foo sera un symbole. L'avantage des symboles est qu'ils sont uniques. Lorsque vous appelez un élément du hachage, vous faites hash[:foo].

Les symboles nécessitent moins de mémoire que les chaînes, ce qui les rend également utiles si vous souhaitez rendre votre programme un peu plus rapide.

2
Charles

Toutes ces réponses omettent un détail très tentant. Si vous définissez le symbole: foo, vous obtenez .. devinez quoi .. la chaîne "foo". Par conséquent

irb(main):025:0>
irb(main):026:0> :foo
=> :foo
irb(main):027:0> "#{:foo}"
=> "foo"
irb(main):028:0>
irb(main):029:0> 'foo' <=> :foo
=> nil
irb(main):030:0> 'foo' <=> :foo.to_s
=> 0
irb(main):031:0>

D'où .. pour les programmeurs Perl .. c'est la réponse de Ruby au "mot nu".

0
Frank Carnovale

C'est un symbole En gros, vous dites que les deux éléments du hachage ont les clés bla et bloop, un peu comme si vous aviez utilisé les chaînes "bla" et "bloop". Cependant, ils utilisent moins de mémoire que les chaînes et sont plus faciles à taper.

0
kindall