85 votes

La Compréhension Des Symboles Dans Ruby

Malgré la lecture de "la Compréhension de Ruby Symboles", je suis toujours confus par la représentation des données dans la mémoire quand il s'agit de l'utilisation de symboles. Si un symbole, deux d'entre eux contenues dans des objets différents, existent dans le même emplacement de mémoire, alors comment est-il qu'ils contiennent différentes valeurs? J'aurais attendu le même emplacement de mémoire pour contenir la même valeur. Un devis à partir du lien:

Contrairement aux chaînes de caractères, symboles du même nom sont initialisés et d'exister dans la mémoire qu'une seule fois au cours d'une session de ruby

Je ne comprends pas comment il parvient à différencier les valeurs contenues dans le même emplacement de mémoire.


MODIFIER

Considérons donc l'exemple:

patient1 = { :ruby => "red" }
patient2 = { :ruby => "programming" }

patient1.each_key {|key| puts key.object_id.to_s}
3918094
patient2.each_key {|key| puts key.object_id.to_s}
3918094

patient1 et patient2 sont à la fois des tables de hachage, c'est bien. :ruby , cependant, est un symbole. Si nous étions de sortie suivants:

patient1.each_key {|key| puts key.to_s}

Puis ce sera sortie? "red"ou "programming"?


MODIFIER

Je suis encore très très confus. Je pense à un symbole est un pointeur sur une valeur. Oubliez les hachages pour une seconde. Les questions que j'ai sont; vous pouvez assigner une valeur à un symbole? Est un symbole juste un pointeur vers une variable avec une valeur en elle? Si les symboles sont mondiaux, cela signifie un symbole renvoie toujours à une chose?

63voto

anshul Points 2964

Réfléchissez à ceci:

x = :sym
y = :sym
(x.__id__ == y.__id__ ) && ( :sym.__id__ == x.__id__) # => true

x = "string"
y = "string"
(x.__id__ == y.__id__ ) || ( "string".__id__ == x.__id__) # => false

Si, toutefois, vous créez un objet symbole, tant que son contenu sont les mêmes, il va se référer au même objet en mémoire. Ce n'est pas un problème, car un symbole est un objet immuable. Les chaînes sont mutables.

Edit: En réponse à la remarque ci-dessous)

Dans l'article original, la valeur n'est pas stockée dans un symbole, elle est stockée dans une table de hachage. Réfléchissez à ceci:

hash1 = { "string" => "value"}
hash2 = { "string" => "value"}

Cela crée six objets dans la mémoire -- quatre objets string et deux de hachage objets.

hash1 = { :symbol => "value"}
hash2 = { :symbol => "value"}

Ceci crée seulement cinq objets en mémoire -- un symbole, les deux chaînes et deux de hachage objets.

55voto

Segfault Points 3311

J'ai été en mesure de grock symboles quand je pensais à elle comme ça. Un Rubis chaîne de caractères est un objet qui a un tas de méthodes et de propriétés. Les gens aiment utiliser les cordes pour les clés, et lorsque la chaîne est utilisé pour une clé, puis toutes les méthodes ne sont pas utilisées. Donc, ils ont fait des symboles, qui sont des objets de chaîne avec toutes les fonctionnalités supprimées, à l'exception de ce qui est nécessaire pour une bonne clé.

Il suffit de penser de symboles comme les chaines.

34voto

jcdyer Points 7956

Le symbole :ruby ne contient pas d' "red" ou "programming". Le symbole :ruby est juste le symbole :ruby. Il est de votre hache, patient1 et patient2 qui contiennent chacune de ces valeurs, dans chaque cas signalé par la même clé.

Pensez-y de cette façon: Si vous allez dans le salon le matin de noël, et de voir deux boîtes avec une étiquette sur eux que de dire "Kezzer" sur eux. Sur a des chaussettes en elle, et l'autre a charbon. Vous n'allez pas à se confondre et se demander comment "Kezzer" peut contenir à la fois des chaussettes et du charbon, même si c'est le même nom. Parce que le nom n'est pas contenant le (de merde) présente. C'est juste pointant sur eux. De même, :ruby ne contient pas de valeurs de hachage, c'est juste des points à eux.

27voto

tadman Points 70178

Vous pourriez être en supposant que la déclaration que vous avez faite définit la valeur d'un Symbole à être autre chose que ce qu'il est. En fait, un Symbole est juste un "internalisés" Chaîne de valeur reste constante. C'est parce qu'ils sont stockés à l'aide d'un simple identifiant entier qu'ils sont fréquemment utilisés comme qui est plus efficace que la gestion d'un grand nombre de chaînes de longueur variable.

Prenons le cas de votre exemple:

patient1 = { :ruby => "red" }

Ce doit être lu comme suit: "déclarer une variable patient1 et de définir une table de Hachage, et dans ce magasin, la valeur "rouge" sous la clé (symbole 'ruby')"

Une autre façon d'écrire c'est:

patient1 = Hash.new
patient1[:ruby] = 'red'

puts patient1[:ruby]
# 'red'

Comme vous êtes de procéder à une affectation, il n'est guère surprenant que le résultat que vous obtenez en retour est identique à ce que vous avez attribué à en premier lieu.

Le Symbole concept peut être un peu déroutant, car il n'est pas une caractéristique de la plupart des autres langues.

Chaque objet de type String est visible, même si les valeurs sont identiques:

[ "foo", "foo", "foo", "bar", "bar", "bar" ].each do |v|
  puts v.inspect + ' ' + v.object_id.to_s
end

# "foo" 2148099960
# "foo" 2148099940
# "foo" 2148099920
# "bar" 2148099900
# "bar" 2148099880
# "bar" 2148099860

Chaque Symbole avec la même valeur se réfère au même objet:

[ :foo, :foo, :foo, :bar, :bar, :bar ].each do |v|
  puts v.inspect + ' ' + v.object_id.to_s
end

# :foo 228508
# :foo 228508
# :foo 228508
# :bar 228668
# :bar 228668
# :bar 228668

La conversion de chaînes de symboles de cartes de valeurs identiques pour le même Symbole unique:

[ "foo", "foo", "foo", "bar", "bar", "bar" ].each do |v|
  v = v.to_sym
  puts v.inspect + ' ' + v.object_id.to_s
end

# :foo 228508
# :foo 228508
# :foo 228508
# :bar 228668
# :bar 228668
# :bar 228668

De même, la conversion du Symbole à la Chaîne crée un distinctes de chaîne à chaque fois:

[ :foo, :foo, :foo, :bar, :bar, :bar ].each do |v|
  v = v.to_s
  puts v.inspect + ' ' + v.object_id.to_s
end

# "foo" 2148097820
# "foo" 2148097700
# "foo" 2148097580
# "bar" 2148097460
# "bar" 2148097340
# "bar" 2148097220

Vous pouvez penser à des valeurs de Symbole comme étant prélevé à partir d'une table de Hachage interne et vous pouvez voir toutes les valeurs qui ont été codées à l'aide de Symboles à l'aide d'un simple appel de méthode:

Symbol.all_values

# => [:RUBY_PATCHLEVEL, :vi_editing_mode, :Separator, :TkLSHFT, :one?, :setuid?, :auto_indent_mode, :setregid, :back, :Fail, :RET, :member?, :TkOp, :AP_NAME, :readbyte, :suspend_context, :oct, :store, :WNOHANG, :@seek, :autoload, :rest, :IN_INPUT, :close_read, :type, :filename_quote_characters=, ...

Comme vous le définir de nouveaux symboles, soit par le colon-notation ou par l'aide .to_sym ce tableau va croître.

13voto

meagar Points 85475
patient1.each_key {|key| puts key.to_s}

Puis ce sera la sortie? "rouge", ou "la programmation"?

Ni, il sera sortie "ruby".

Vous êtes à la confusion des symboles et des valeurs de hachage. Ils ne sont pas liés, mais ils sont utiles ensemble. Le symbole en question est - :ruby; il n'a rien à voir avec les valeurs dans la table de hachage, et c'interne de représentation entière sera toujours le même, et c'est la "valeur" (lors de la conversion d'une chaîne de caractères) sera toujours "ruby".

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