Table of contentsClick link to navigate to the desired location
This content has been automatically translated from Ukrainian.
First, we need to understand what immediate value and reference are in Ruby.
Immediate value in programming is a value that is stored directly in a variable or object, without referencing another area of memory. This can be a number, a symbol, true, false, or nil. For example, when you assign a number to a variable, that is an immediate value.
Reference points to an area of memory where an object is stored. Objects that are typically stored using references include strings, arrays, hashes, and class objects. When you work with an object through a reference, you are actually working with the area of memory where the object itself is stored.
In the post about assigning a variable in ruby, we discussed the concept of reference. But we did not cover immediate values.
Immediate values in Ruby
Immediate value is a value that is stored directly in a variable, rather than through a reference to an object. However, there is one point that personally confused me a bit. In Ruby, even for immediate values, variables have an object_id, but they point to a specific location in memory where the value is stored, not to an object, as is the case with references. That is, in the case of immediate values, object_id does not point to an object in memory, but simply identifies a specific value that is stored directly in the variable. So, in Ruby, not everything is an object.
A quote from apidock:
object_id() public 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. Note: that some objects of builtin classes are reused for optimization. This is the case for immediate values and frozen string literals. Immediate values are not passed by reference but are passed by value: nil, true, false, Fixnums, Symbols, and some Floats.
These values are stored directly in variables and cannot be changed through a reference to an object. They are the most efficient way to store data in memory, as they do not require memory allocation for an object. This is done for memory optimization. There is no point in creating new objects for each nil. So let's play a bit with IRB.
A string is an object.
a = 'hehe' b = 'hehe' a == b => true # The strings are indeed the same a.object_id == b.object_id => false # We have two different objects to store the same content
Symbols are immediate values
a = :test => :test b = :test => :test a.object_id == b.object_id => true # We have one value in memory, and two variables pointing to it
The same goes for true, false, and nil
a = true b = true a.object_id == b.object_id => true a = false b = false a.object_id == b.object_id => true a = nil b = nil a.object_id == b.object_id => true
Ruby reserves certain object IDs for these objects immediate values, as each variable assigned an immediate value points to the same location in memory. Let's check:
true.object_id => 20 false.object_id => 0 nil.object_id => 4 a = true => true b = false => false c = nil => nil a.object_id => 20 b.object_id => 0 c.object_id => 4
And better yet - let's write rspec:
require 'rspec'
describe "Immediate values and references in Ruby" do
it "demonstrates immediate values vs references" do
# Immediate values
a = 5
b = a
expect(a.object_id).to eq(b.object_id)
# Reference
a = [1, 2, 3]
b = a
expect(a.object_id).to eq(b.object_id)
end
it "demonstrates object_id for immediate values" do
# True
a = true
b = true
expect(a.object_id).to eq(b.object_id)
# False
a = false
b = false
expect(a.object_id).to eq(b.object_id)
# Nil
a = nil
b = nil
expect(a.object_id).to eq(b.object_id)
end
it "demonstrates object_id for symbols" do
a = :test
b = :test
expect(a.object_id).to eq(b.object_id)
end
it "demonstrates object_id for frozen literals" do
a = 'test'.freeze
b = 'test'.freeze
expect(a.object_id).to eq(b.object_id)
end
it "demonstrates static object_id for true, false, nil" do
expect(true.object_id).to eq(20)
expect(false.object_id).to eq(0)
expect(nil.object_id).to eq(4)
end
end
Finished in 0.01952 seconds (files took 0.27884 seconds to load) 5 examples, 0 failures
I hope this information helps someone understand a bit about immediate value and reference in Ruby.
This post doesn't have any additions from the author yet.