Cała oryginalna treść jest tworzona po ukraińsku. Nie wszystkie treści zostały jeszcze przetłumaczone. Niektóre posty mogą być dostępne tylko po ukraińsku.Dowiedz się więcej

Jaka jest różnica między wartością bezpośrednią a referencją w Ruby?

Okładka posta: Jaka jest różnica między wartością bezpośrednią a referencją w Ruby?
Spis treściKliknij link, aby przejść do wybranego miejsca
Ta treść została automatycznie przetłumaczona z ukraińskiego.
Na początku trzeba zrozumieć, czym jest immediate value oraz reference w Ruby.
Bezpośrednia wartość (immediate value) w języku programowania to wartość, która jest przechowywana bezpośrednio w zmiennej lub obiekcie, bez odniesienia do innego obszaru pamięci. Może to być liczba, symbol, true, false lub nil. Na przykład, gdy przypisujesz liczbę do zmiennej, to jest to bezpośrednia wartość.
Referencja (reference) wskazuje na obszar pamięci, w którym przechowywany jest obiekt. Obiekty, które zazwyczaj są przechowywane za pomocą referencji, obejmują łańcuchy, tablice, hashe i obiekty klas. Gdy pracujesz z obiektem za pomocą referencji, tak naprawdę pracujesz z obszarem pamięci, w którym przechowywany jest sam obiekt.
W poście o przypisaniu zmiennej w ruby omówiliśmy koncepcję referencji (reference). Ale nie omówiliśmy bezpośrednich wartości.

Bezpośrednie wartości w Ruby

Bezpośrednia wartość to wartość, która jest przechowywana bezpośrednio w zmiennej, a nie przez odniesienie do obiektu. Ale jest jeden aspekt, który osobiście mnie trochę zmylił. W Ruby nawet dla bezpośrednich wartości zmienne mają object_id, ale wskazują one na konkretne miejsce w pamięci, gdzie przechowywana jest wartość, a nie na obiekt, jak w przypadku referencji. To znaczy, w przypadku bezpośrednich wartości object_id nie wskazuje na obiekt w pamięci, a po prostu identyfikuje konkretną wartość, która jest przechowywana bezpośrednio w zmiennej. Tak, w Ruby nie wszystko jest obiektem.
Cytat z apidock:
object_id() public

Zwraca całkowity identyfikator dla obj.

Ta sama liczba będzie zwracana przy wszystkich wywołaniach object_id dla danego obiektu, a żadne dwa aktywne obiekty nie będą dzielić id.

Uwaga: niektóre obiekty klas wbudowanych są ponownie używane w celu optymalizacji. Dotyczy to bezpośrednich wartości i zamrożonych literałów łańcuchowych.

Bezpośrednie wartości nie są przekazywane przez referencję, ale są przekazywane przez wartość: nil, true, false, Fixnumy, symbole i niektóre liczby zmiennoprzecinkowe.
Te wartości są przechowywane bezpośrednio w zmiennych i nie mogą być zmieniane przez odniesienie do obiektu. Są najbardziej efektywnym sposobem przechowywania danych w pamięci, ponieważ nie wymagają przydzielania pamięci dla obiektu. Zrobiono to w celu optymalizacji pamięci. Nie ma sensu tworzyć nowych obiektów dla każdego nil. Więc zróbmy trochę zabawy z IRB.
Łańcuch to obiekt.
a = 'hehe'
b = 'hehe'

a == b
=> true # Łańcuchy są naprawdę identyczne

a.object_id == b.object_id
=> false # Mamy dwa różne obiekty do przechowywania tej samej zawartości 
Symbole - bezpośrednie wartości
a = :test
=> :test
b = :test
=> :test
a.object_id == b.object_id
=> true # Mamy jedną wartość w pamięci i dwie zmienne, które na nią wskazują
To samo dotyczy true, false i 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 rezerwuje pewne identyfikatory obiektów dla tych obiektów bezpośrednich wartości, ponieważ każda zmienna, która ma przypisaną bezpośrednią wartość - wskazuje na to samo miejsce w pamięci. Sprawdźmy:
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
A lepiej - napiszmy rspec:
require 'rspec'

describe "Bezpośrednie wartości i referencje w Ruby" do
  it "demonstruje bezpośrednie wartości vs referencje" do
    # Bezpośrednie wartości
    a = 5
    b = a
    expect(a.object_id).to eq(b.object_id)

    # Referencja
    a = [1, 2, 3]
    b = a
    expect(a.object_id).to eq(b.object_id)
  end

  it "demonstruje object_id dla bezpośrednich wartości" 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 "demonstruje object_id dla symboli" do
    a = :test
    b = :test
    expect(a.object_id).to eq(b.object_id)
  end

  it "demonstruje object_id dla zamrożonych literałów" do
    a = 'test'.freeze
    b = 'test'.freeze
    expect(a.object_id).to eq(b.object_id)
  end

  it "demonstruje statyczny object_id dla 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
Mam nadzieję, że ta informacja pomoże komuś lepiej zrozumieć immediate value oraz reference w Ruby.

Ten post nie ma jeszcze żadnych dodatków od autora.

Co to jest "rozprzestrzenienie zakresu" (Scope Creep / Skołp krip)?
13 maj 07:20

Co to jest "rozprzestrzenienie zakresu" (Scope Creep / Skołp krip)?

meme code
meme code@memecode
Co oznacza "Nattywny"?
22 maj 07:01

Co oznacza "Nattywny"?

meme code
meme code@memecode
Jak działa 'rails console --sandbox'?
23 maj 19:39

Jak działa 'rails console --sandbox'?

meme code
meme code@memecode
Do czego potrzebna jest baza danych CVE (Wspólne Luki i Ekspozycje)?
29 maj 08:05

Do czego potrzebna jest baza danych CVE (Wspólne Luki i Ekspozycje)?

meme code
meme code@memecode
29 maj 09:09

Jakie systemy operacyjne wspierają Ruby?

meme code
meme code@memecode
Czy Ruby tworzy nową kopię obiektu podczas przypisywania zmiennej do zmiennej?
29 maj 09:30

Czy Ruby tworzy nową kopię obiektu podczas przypisywania zmiennej do zmiennej?

meme code
meme code@memecode
Dlaczego kod Ruby zwraca nil po wykonaniu puts?
29 maj 20:30

Dlaczego kod Ruby zwraca nil po wykonaniu puts?

meme code
meme code@memecode
Jaka jest różnica między nil a false w Ruby?
29 maj 20:59

Jaka jest różnica między nil a false w Ruby?

meme code
meme code@memecode
Dlaczego pusty ciąg (string) w Ruby nie jest fałszem?
31 maj 14:39

Dlaczego pusty ciąg (string) w Ruby nie jest fałszem?

meme code
meme code@memecode
Zakres widoczności zmiennej lokalnej w Ruby
3 cze 16:46

Zakres widoczności zmiennej lokalnej w Ruby

meme code
meme code@memecode
Czym różni się int od bigint w Ruby? Minimalne i maksymalne wartości.
13 cze 06:37

Czym różni się int od bigint w Ruby? Minimalne i maksymalne wartości.

meme code
meme code@memecode
Co oznacza błąd 'is out of range' w Ruby on Rails? Błąd zakresu - Liczba całkowita z limitem 4 bajtów
13 cze 07:18

Co oznacza błąd 'is out of range' w Ruby on Rails? Błąd zakresu - Liczba całkowita z limitem 4 bajtów

meme code
meme code@memecode