In Ruby I can write some things in two different ways:
I can do this:
:algo
Or this:
'algo'
What's the difference?
In Ruby I can write some things in two different ways:
I can do this:
:algo
Or this:
'algo'
What's the difference?
Short version : Use :simbolos
for code control strings, and "strings"
for what will appear on the user screen.
The first thing to be said is that you should not confuse strings with symbols. When you type :string
, you are instantiating a symbol. When you type "string"
you are instantiating a string. Let's see this in practice:
:string.class
=> Symbol
'string'.class
=> String
The methods that are available for String
objects are not the same as those that are available for Symbol
objects. So often these objects are not interchangeable.
The biggest difference between a symbol and a string is that a symbol is immutable . This means that once it is instantiated, it is impossible to change its value. A string, on the other hand, is changeable. For example,
you can use the tr!
method to change the value of a string:
a = 'string'
=> "string"
a
=> "string" # valor da string
a.tr!('i', 'e')
=> "streng"
a
=> "streng" # mesma variável possui outro valor agora
A very important difference is that an object of the symbol class never has its memory deallocated, unlike a string. Ruby is an interpreted language that has a garbage collector - this means that you do not you have to allocate and deallocate memory manually as needed in lower-level languages like C (through the malloc
, for example). When you no longer use a string, the ruby garbage collector discards that string. This never happens with symbols. To release the memory consumed by the symbols, there is only one way: Exiting your program.
When a program consumes more and more memory without ever releasing it, this program is leaking memory . If you let it run forever, the memory used is getting bigger and bigger. This is not desirable for programs that will run for a long time, for example an application in Rails. To avoid this, you should not dynamically create symbols in the program in unknown strings. For example, using the to_sym
method on user data entry.
Now that I've freaked out, let's get the good part of the symbols :-)
Since they are immutable, you do not need to instantiate them every time they appear in the program. This means that it ruby notes that a symbol like that already exists, and uses it again, as many times as necessary. Let's prove this:
"minha string".object_id == "minha_string".object_id
=> false
:simbolo.object_id == :simbolo.object_id
=> true
As you can see, the first line instantiates two different objects, while the second uses twice the same object. This proves that ruby reuses symbols, but not strings.
Okay, cool. I dont care? The problem is that instance or compare strings takes much longer than instanceing or comparing symbols. So, although you lose a bit by constantly using more memory, operations with symbols are usually faster. As we have seen, the comparison of a symbol can be done with object_id
, while a string is made by comparing the internal value. This is much more expensive for the processor, which works at the bit level, where numbers are represented using much less space than strings.
Do not say that you will compare a symbol manually. For example, using symbols as keys for an object of type Hash
in which the values will be fetched often greatly increases performance, precisely by comparing symbols to be faster than strings.
By their characteristics, the Symbols were thought to be used for code control. For example, for keys in a dictionary or an attribute tipo
of an object. You will constantly use these values in code, and are used for comparison (direct in the case of the attribute, implicit in the case of a hash key). This is why it is more advantageous to use symbols and avoid getting a new string every time your code is used.
Strings shine when values are manipulated, or when they are dynamically defined. For example, for a user's nickname for a site - there are many users and hardly everyone will enter the site at the same time, so there is no reason to use symbol and suffer with increased memory.
When you create a string using :string
, this string is unique in the whole program, ie the system checks if a string with these characters already exists, and if it exists, it reuses it create a new one. This type of string is called symbol , and in addition to single it is also immutable .
When using 'string'
, a new object is created, usually without regard to whether there are already others with the same content (same string) or not. That way, two strings can be "equal" but have different identities :
:algo == :algo # true
:algo.equal? :algo # true
'algo' == 'algo' # true
'algo'.equal? 'algo' # false
Source: this question in SOen (see also this other question )
Note: Because strings and symbols are different types, comparing them using ==
will always return false
, even though its contents are the same. If you have variables that can be of one type or another, and want to know if your content is the same, you can use .to_s
on both sides of the comparison:
:algo == 'algo' # false
:algo.to_s == 'algo'.to_s # true