ГоловнаВсі публікаціїКатегоріїПро проєкт

В чому різниця між immediate value та reference у Ruby?

Обкладинка нотатки: В чому різниця між immediate value та reference у Ruby?
Зміст дописунатисність на посилання, щоб перейти до потрібного місця
Спочатку треба розібратись що таке таке immediate value та reference у Ruby.
Безпосереднє значення (immediate value) в мові програмування - це значення, яке зберігається напряму в змінній або об'єкті, без посилання на іншу область пам'яті. Це може бути число, символ, true, false або nil. Наприклад, коли ви присвоюєте змінній число, це безпосереднє значення.
Посилання (reference) вказує на область пам'яті, де зберігається об'єкт. Об'єкти, які зазвичай зберігаються за допомогою посилань, включають строки, масиви, хеші та об'єкти класів. Коли ви працюєте з об'єктом за допомогою посилання, ви фактично працюєте з областю пам'яті, де зберігається сам об'єкт.
У дописі про призначення змінної змінній у ruby ми розглянули концепцію посилання (reference). Але не розглянули безпосередні значення.

Immediate values у Ruby

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. 
Що таке "розповзання скоупу" (Scope Creep / Скоуп кріп)?
13.05.2024 07:20

Що таке "розповзання скоупу" (Scope Creep / Скоуп кріп)?

meme code
meme code@memecode
Що означає "Нативний"?
22.05.2024 07:01

Що означає "Нативний"?

meme code
meme code@memecode
Як працює 'rails console --sandbox'?
23.05.2024 19:39

Як працює 'rails console --sandbox'?

meme code
meme code@memecode
Для чого потрібна база даних CVE (Common Vulnerabilities and Exposures)?
29.05.2024 08:05

Для чого потрібна база даних CVE (Common Vulnerabilities and Exposures)?

meme code
meme code@memecode
29.05.2024 09:09

Які операційні системи підтримують Ruby?

meme code
meme code@memecode
Чи створює Ruby нову копію об’єкта при присвоєнні змінної змінній?
29.05.2024 09:30

Чи створює Ruby нову копію об’єкта при присвоєнні змінної змінній?

meme code
meme code@memecode
Чому Ruby код повертає nil після виконання puts?
29.05.2024 20:30

Чому Ruby код повертає nil після виконання puts?

meme code
meme code@memecode
Яка різниця між nil і false в Ruby?
29.05.2024 20:59

Яка різниця між nil і false в Ruby?

meme code
meme code@memecode
Чому порожній рядок (string) у Ruby не є false?
31.05.2024 14:39

Чому порожній рядок (string) у Ruby не є false?

meme code
meme code@memecode
Область видимості локальної змінної в Ruby
03.06.2024 16:46

Область видимості локальної змінної в Ruby

meme code
meme code@memecode
Чим відрізняється int та bigint в Ruby? Мінімальні та максимальні значення.
13.06.2024 06:37

Чим відрізняється int та bigint в Ruby? Мінімальні та максимальні значення.

meme code
meme code@memecode
Що означає помилка 'is out of range' в Ruby on Rails? Range Error - Integer with limit 4 bytes
13.06.2024 07:18

Що означає помилка 'is out of range' в Ruby on Rails? Range Error - Integer with limit 4 bytes

meme code
meme code@memecode