AlbertMunichMar
AlbertMunichMar

Reputation: 1866

Ruby immutability of strings and symbols (What if we store them in variables)

A string is a primitive type; whenever you call the string, it has a new object id. A symbol is a referenced type; whenever you create a symbol, you create a pointer, which points to the value.

I stored symbols in variables:

var1 = :foo
var1.object_id # => 2598748
:foo.object_id # => 2598748

var2 = :foo
var2.object_id # => 2598748

var2 = "hello"
var2.object_id # => 70131755422100

How is it possible that I create a second variable var2, and it has the same object id as var1? I create a second element. Does it mean that variables are also pointers?

Both variables point to the symbol :foo. The symbol :foo is stored just once, right?

Two variables are created, so they should be in the memory, and they cannot be in the same place because they have different names. var1 and var2 need to be stored, so that I can call them later. I don't get how I can call them if they have the same object id. If someone can help me to understand this, I'd be thankful.

Upvotes: 1

Views: 338

Answers (1)

David Bodow
David Bodow

Reputation: 717

Ruby variables are references to objects, so when you send a method to a variable, the object it references is the context in which it is evaluated. It's probably more clear to look at the first image in the top rated answer (below the accepted answer) here.

So, to figure out what's going on, let's dig into the documentation a bit and see what happens with your code snippet.

Ruby's Symbol class documentation: https://ruby-doc.org/core-2.5.0/Symbol.html

Symbol objects represent names and some strings inside the Ruby interpreter. They are generated using the :name and :"string" literals syntax, and by the various to_sym methods. The same Symbol object will be created for a given name or string for the duration of a program's execution, regardless of the context or meaning of that name. Thus if Fred is a constant in one context, a method in another, and a class in a third, the Symbol :Fred will be the same object in all three contexts.

Ruby's Object#object_id documentation: https://ruby-doc.org/core-2.5.1/Object.html#method-i-object_id

Returns an integer identifier for obj.

The same number will be returned on all calls to object_id for a given object, and no two active objects will share an id.

So here's what's happening step-by-step:

# We create two variables that refer to the same object, :foo
var1 = :foo
var2 = :foo

var1.object_id = 2598748
var2.object_id = 2598748
# Evaluated as:
# var1.object_id => :foo.object_id => 2598748
# var2.object_id => :foo.object_id => 2598748

As discussed in the first link above, Ruby is pass-by-value, but every value is an Object, so your variables both evaluate to the same value. Since every symbol made of the same string ("foo" in this case) refers to the same object, and Object#object_id always returns the same id for the same object, you get the same id back.

Upvotes: 2

Related Questions