Sens zamrażania stringu

Właśnie jestem przy obiektach String i przy zamrażaniu. Zauważyłem, że jak się zamrozi obiekt

str = "const" str,freeze
to concatować się nie da:

str.concat("variable")

wywali:

Tylko zastanawia mnie sens. Właściwie wszystko inne (na przykład):

str += " not"

zadziała. Wiem, że pod spodem podmianiają się tylko referencje do tworzonego na nowo obiektu - ale takie zarożenie, które tego nie bloku jest nic nie warte bo z jednej strony wiem, że to już nie jest ten sam obiekt, a z drugiej strony chciałem się obronić przed możliwością zmiany jego zawartości - a go straciłem… :confused: Czy freeze ma jakieś sensowne zastosowanie ?

Mylisz tutaj dwie rzeczy - niemodyfikowalność obiektu ze “stałością” zmiennej. W pierwszym przypadku nie możesz na obiekcie (do którego może przecież odnosić się wiele zmiennych) wywołać metody, która powoduje jego modyfikację (np. przypisuje nową wartość którejś z jego zmiennych instancyjnych). W drugim przypadku chodzi o to, że jakieś odniesienie (zmienna/stała?) nie może się zmienić, tzn. że raz przypisany do niej obiekt nie może zostać zastąpiony innym.

Pierwszy przypadek ilustruje następujący fragment kodu:

a = "Abc" b = "Abc" a.freeze b.concat "zzz" #=> Error
Czy da się jakoś osiągnąć drugi przypadek? Teoretycznie w Rubim występują stałe - zaczynają się od wielkiej litery. Ale… niestety można zmienić przypisaną do nich wartość. Bardzo wielu ludzi to denerwuje, mnie też. Interpreter wygeneruje tylko ostrzeżenie:

A = "a" A = "b" #=> warning: already initialized constant A
Zatem to co chciałbyś osiągnąć powinno być kombinacją freeze i użycia stałej, tyle, że niestety i tak nie daje nam to gwarancji, że ktoś nam tego nie zmieni… niestety. Miejmy nadzieje, że Matz w końcu uczyni ze stałych prawdziwe STAŁE.

BTW: to mój setny post :slight_smile:

No właśnie, też mnie uderzyło to, że stałe są zmienianlne - jak przeczytałem pierwszy raz o freeze to myślałem - no w końcu jednak się da, a tutaj kicha … Dzięki za wyjaśnienie. Oddaję się dalszej lekturze …

Ależ jak najbardziej się da :slight_smile:

Freeze nie pozwala na zmianę in-place, na modyfikację danej instancji stringu. Natomiast nie ma wpływu na zmienną do której jest ona przypisany. A += tworzy nowy string i przypisuje go do starej zmiennej:

[code]>> string = “test”
=> “test”

string.object_id
=> 283360
string.freeze
=> “test”
frozen = string
=> “test”
frozen.object_id
=> 283360
string.concat(“x”)
TypeError: can’t modify frozen string
from (irb):6:in `concat’
from (irb):6
from :0
string += “x”
=> “testx”
string.object_id
=> 244610
frozen
=> “test”
frozen.object_id
=> 283360
[/code]