Quand je dis { :bla => 1, :bloop => 2 }
, qu'est-ce que ça fait exactement :
? J'ai lu quelque part comment cela ressemble à 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?
Quand je dis { :bla => 1, :bloop => 2 }
, qu'est-ce que ça fait exactement :
? J'ai lu quelque part comment cela ressemble à 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?
Réponses:
:foo
est un symbole nommé "foo". Les symboles ont la particularité 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 (car seule une comparaison de pointeurs est impliquée, par opposition à la comparaison de tous les caractères comme vous le feriez dans une chaîne), et vous n'aurez pas non plus un million de copies du même symbole flottant.
De plus, contrairement aux chaînes, les symboles sont immuables.
"foo".equal? "foo"
faux? b) Pouvez-vous faire référence à un symbole n'importe où, ce qui en fait essentiellement des variables globales?
equal?
dans Ruby fait une comparaison d'identité. Chaque littéral de chaîne, comme "foo"
, crée une nouvelle instance de chaîne. Cela fonctionne de cette façon car les chaînes de Ruby sont mutables. 2. Les symboles sont globaux, mais ressemblent plus à des constantes globales qu'à des variables globales, car les symboles n'ont pas d'état. Ainsi, l'utilisation de symboles n'est pas un contre-modèle à la manière des variables globales.
"foo" == "foo"
# => true
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 génère:
"foo".equal? "foo" -> false
"foo" == "foo" -> true
:foo.equal? :foo -> true
:foo == :foo -> true
Ainsi, la comparaison d'une chaîne à une chaîne utilisant equal?
échoue car ce sont des objets différents, même s'ils ont un contenu égal. ==
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 symboles sont fondamentalement les mêmes en ce qui concerne la vitesse. Après 1000000 d'itérations, il n'y a que 0,004733 seconde de différence, donc je dirais que c'est un lavage entre lequel utiliser.
==
résultats ont été plus rapides que .equal?
pour les comparaisons de chaînes et de symboles. La comparaison des symboles a produit 3+ fois plus rapidement que les comparaisons de chaînes.
Les symboles sont un moyen de représenter des chaînes et des noms en rubis.
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 lors d'une session de rubis.
Ils sont utiles lorsque vous devez utiliser le même mot pour représenter différentes choses
Il y a quelques citations du célèbre livre Agile Web Development with Rails , qui peuvent également être utiles pour comprendre le symbole :
Rails utilise des symboles pour identifier les choses. En particulier, il les utilise comme clés pour nommer les paramètres des méthodes et rechercher les choses dans des hachages.
redirect_to :action => "edit", :id => params[:id]
Vous pouvez considérer les symboles comme des littéraux de chaîne qui sont magiquement transformés en constantes. Alternativement, vous pouvez considérer les deux points comme signifiant "la chose nommée", donc: id est "la chose nommée id".
En rubis, chaque objet a un identifiant d'objet unique, si vous écrivez puts "hello".object_id
dans votre IRB et appuyez sur Retour pendant 2 fois différentes, vous obtiendrez 2 valeurs de retour différentes, mais si vous écrivez :hello.object_id
2 fois, vous n'obtiendrez que la même valeur de retour. Cela aurait dû expliquer la différence.
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 le 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.
Toutes ces réponses omettent un détail supplémentaire alléchant .. si vous stringifiez 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>
Par conséquent .. pour les programmeurs Perl .. c'est la réponse de Ruby au «mot nu».
Si vous connaissez Java, vous savez peut-être que les chaînes en Java sont immuables. Les symboles sont similaires en ce sens dans Ruby. Ils sont immuables, c'est-à-dire que n'importe quel nombre d'occurrences d'un symbole particulier :symbol
sera mappé à une seule adresse mémoire. Et, par conséquent, il est recommandé d'utiliser des symboles dans la mesure du possible car il optimise l'utilisation de la mémoire.
NSString
. Il y "foo"
aura toujours égal à "foo"
, car les chaînes internes identiques sont simplement désignées. Mais la réponse serait encore confuse.