Спочатку треба розібратись що таке таке
immediate value та
reference у Ruby.
Безпосереднє значення (immediate value) в мові програмування - це
значення, яке зберігається напряму в змінній або об'єкті, без посилання на іншу область пам'яті. Це може бути число, символ, true, false або nil. Наприклад, коли ви присвоюєте змінній число, це безпосереднє значення.
Посилання (reference) вказує на область пам'яті, де зберігається
об'єкт. Об'єкти, які зазвичай зберігаються за допомогою посилань, включають строки, масиви, хеші та об'єкти класів. Коли ви працюєте з об'єктом за допомогою посилання, ви фактично працюєте з областю пам'яті, де зберігається сам об'єкт.
У дописі про
призначення змінної змінній у ruby ми розглянули концепцію посилання (reference). Але не розглянули безпосередні значення.
Immediate value - це значення, яке зберігається безпосередньо в змінній, а не через посилання на об'єкт. Але є один момент, який особисто мене трохи збив з пантелику. У Ruby навіть для immediate value змінні мають object_id, але вони вказують на конкретне місце в пам'яті, де зберігається значення, а не на об'єкт, як у випадку посилань. Тобто, у випадку immediate value object_id не вказує на об'єкт в пам'яті, а просто ідентифікує конкретне значення, яке зберігається безпосередньо в змінній. Так, в Ruby не все є об'єктом.
Цитата з 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.
Ці значення зберігаються безпосередньо в змінних та не можуть бути змінені через посилання на об'єкт. Вони є найбільш ефективним способом зберігання даних у пам'яті, оскільки не потребують виділення пам'яті для об'єкта. Зроблено це задля оптимізації пам'яті. Немає сенсу створювати нові об'єкти під кожен nil. Тож давайте трохи пограємось з IRB.
Строка - це об'єкт.
a = 'hehe'
b = 'hehe'
a == b
=> true # Строки й справді однакові
a.object_id == b.object_id
=> false # Ми маємо два різних об'єкти для зберігання однакового контенту
Символи - безпосередні значення
a = :test
=> :test
b = :test
=> :test
a.object_id == b.object_id
=> true # Ми маємо одне значення в пам'яті, та дві змінні, які вказують на нього
Теж саме з true, false та 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 резервує певні object IDs для цих
об'єктів immediate values, оскільки кожна змінна, якій призначено immediate value - посилається на те саме місце в пам'яті. Перевіримо:
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
А краще - напишемо rspec:
require 'rspec'
describe "Immediate values та references в Ruby" do
it "демонструє 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 "демонструє object_id для 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 "демонструє object_id для symbols" do
a = :test
b = :test
expect(a.object_id).to eq(b.object_id)
end
it "демонструє object_id для frozen literals" do
a = 'test'.freeze
b = 'test'.freeze
expect(a.object_id).to eq(b.object_id)
end
it "демонструє статичний object_id для 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
Сподіваюсь комусь ця інфа допоможе трохи розібратись з
immediate value та
reference у Ruby.