What are hashes and symbols in Ruby

Why use symbols as hash keys in Ruby?


Often times, people use symbols as keys in a ruby ​​hash.

What's the advantage over using a string?

E.g.

vs.

Reply:


TL; DR:

Using symbols not only saves time when making comparisons, it also saves memory, as they are only saved once.

Ruby symbols are immutable (cannot be changed), which is a lot easier to look up

Short (ish) answer:

Using symbols not only saves time when making comparisons, it also saves memory, as they are only saved once.

Symbols in Ruby are in basically taken "immutable strings" . This means that they cannot be changed. This means that if the same symbol is referenced multiple times throughout the source code, it will always be stored as the same entity, e.g. B. has the same object ID.

Strings, on the other hand, are changeable and can be changed at any time. This means that Ruby must store every string you mention throughout the source code in a separate entity. For example, if you mentioned a string name multiple times in your source code, Ruby would need to store them all in separate string objects, as these could change later (that's the nature of a Ruby string).

If you use a string as a hash key, Ruby has to evaluate the string and check its contents (and compute a hash function on it) and compare the result with the (hash) values ​​of the keys that are already stored in the hash.

If you use a symbol as a hash key, it implicitly means that it is immutable, so basically Ruby can only do a comparison of the (hash function of the) object ID with the (hash) object IDs of the keys, which are already stored in the hash. (much faster)

Disadvantage: Each symbol occupies a place in the symbol table of the Ruby interpreter that is never released. Symbols are never collected through garbage. A corner case is when you have a large number of symbols (e.g. automatically generated). In this case, you should evaluate how this affects the size of your Ruby interpreter.

Remarks:

When you do string comparisons, Ruby can compare symbols just by their object IDs without having to evaluate them. This is much faster than comparing strings that need to be evaluated.

Whenever you access a hash, Ruby always applies a hash function to compute a "hash key" from the key you are using. You can think of something like an MD5 hash. And then Ruby compares these "hash keys" with one another.

Long answer:

https://web.archive.org/web/20180709094450/http://www.reactive.io/tips/2009/01/11/the-difference-between-ruby-symbols-and-strings

http://www.randomhacks.net.s3-website-us-east-1.amazonaws.com/2007/01/20/13-ways-of-looking-at-a-ruby-symbol/







The reason is efficiency with multiple gains versus a string:

  1. Symbols are immutable, hence the question "What happens if the key changes?" does not have to be asked.
  2. Strings are duplicated in your code and usually take up more space.
  3. Hash lookups need to compute the hash of the keys in order to compare them. This is for strings and constant for symbols.

Additionally, Ruby 1.9 introduced a simplified syntax for hash only with symbol keys (for example), and Ruby 2.0 has keyword arguments that only work for symbol keys.

Remarks :

1) You might be surprised that Ruby treats keys differently than any other type. Indeed:

For string keys only, Ruby uses a frozen copy instead of the object itself.

2) The letters "b", "a" and "r" are only stored once for all occurrences in a program. Before Ruby 2.2, it was a bad idea to keep creating new ones that were never reused because they would stay in the global symbol look-up table forever. Ruby 2.2 will collect them with garbage, so don't worry.

3) In fact, computing the hash for a symbol in Ruby 1.8.x didn't take any time because the object ID was used directly:

This changed in Ruby 1.9.x as the hashes change from one session to the next (including that of):





Subject: What's the advantage over using a string?

  • Styling: It's the Ruby way
  • (Very) slightly faster value searches, as hashing a symbol is like hashing an integer versus hashing a string.

  • Disadvantage: Uses a slot in the program's symbol table that is never released.




I would be very interested in a follow up on frozen strings introduced in Ruby 2.x.

If you are working with numerous strings that come from a text input (I am thinking of HTTP parameters or payload via rack, for example), it is much easier to use strings anywhere.

When you are around dozens of them, but they never change (if they are your business vocabulary), I like to think that freezing can make a difference. I haven't done a benchmark yet, but I think it would be close to toolbar.

We use cookies and other tracking technologies to improve your browsing experience on our website, to show you personalized content and targeted ads, to analyze our website traffic, and to understand where our visitors are coming from.

By continuing, you consent to our use of cookies and other tracking technologies and affirm you're at least 16 years old or have consent from a parent or guardian.

You can read details in our Cookie policy and Privacy policy.