Reputation: 1866
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
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