Ruby - What’s the difference if you use two dots or quotes in a string?

Asked

Viewed 1,331 times

11

In Ruby I can write some things in two different ways:

I can do this:

:algo

Or this:

'algo'

What is the difference?

2 answers

12


Short version: Use :simbolos for code control "strings", and "strings" to what will appear on the user screen.

The first thing to say is that you should not confuse strings with symbols. When you write :string, is instanced a symbol. When you write "string" is instanced a string. Let’s see this in practice:

:string.class
 => Symbol 
'string'.class
 => String 

The methods that are available for objects String are not the same as those available for objects Symbol. 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 instanced, it is impossible to modify its value. A string, on the other hand, is mutable. For example, it is possible to use the method tr! 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

An important difference is that an object of the symbol class never has its memory out of place, unlike a string. Ruby is an interpreted language that has a garbage collector - this means that you do not have to manually allocate and de-locate memory as is required in lower level languages like C (through function malloc, for example). When you no longer use a string, the ruby trash collector discards that string. This never happens with symbols. To free the memory consumed by the symbols, there is only one way: Leaving your program.

When a program consumes more and more memory without ever releasing it, that program is leaking memory. If you let it run forever, the memory used will be 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 create symbols dynamically in the program in unknown strings. For example, using the method to_sym in user data input.

Now that I’ve startled, let’s get to the good part of the symbols :-)

As they are immutable, it is not necessary to instancethem every time they appear in the program. This means that he notes that there is already a symbol like that, 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. What about me? The problem is that instancering or comparing strings takes a lot longer than instanceing or comparing symbols. So despite losing a little using constantly more memory, the operations done with symbols are usually faster.

As we have seen, the comparison of a symbol can be made with object_id, while a string is made by comparing the internal value. This is much more expensive for the processor, which works at bit level, where numbers are represented using much less space than strings.

I don’t say that you will compare a symbol manually. For example, use symbols as keys for an object of the type Hash where values will be searched for often greatly increases performance, exactly by comparing symbols 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 the code, and they are used for comparison (direct in the case of the attribute, implicit in the case of a key for a hash). So it is more advantageous to use symbols and avoid being instanced a new string each time your code is used.

Strings shine when the values are manipulated, or when they are dynamically defined. For example, for the nickname of a user of 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 from memory increase.

6

When creating a string using :string, that string is only throughout the program, i.e. the system checks if a string already exists with these characters, and if it exists it reuses it instead of creating a new one. This type of string is called Symbol (symbol), and apart from unique it is also immutable.

When you use it 'string', create a new object, normally, without taking into account whether there are already others with the same content (same character sequence) or not. That way, two strings can be "equal" but have identities different:

:algo == :algo         # true
:algo.equal? :algo     # true

'algo' == 'algo'       # true
'algo'.equal? 'algo'   # false

Source: that question on Soen (see also that other question)

Note: as strings and symbols are different types, compare them using == will always return false, even if 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

Example in the ideone.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.