Dlaczego klucz sznurkowy jest zamrożony?
Wedługspecyfikacjałańcuchy używane jako klucz do skrótu są duplikowane i zamrażane. Inne zmienne obiekty wydają się nie mieć takiego szczególnego znaczenia. Na przykład za pomocą klucza tablicowego możliwe jest następujące.
a = [0]
h = {a => :a}
h.keys.first[0] = 1
h # => {[1] => :a}
h[[1]] # => nil
h.rehash
h[[1]] # => :a
Z drugiej strony podobnej rzeczy nie można zrobić za pomocą klucza łańcuchowego.
s = "a"
h = {s => :s}
h.keys.first.upcase! # => RuntimeError: can't modify frozen String
Dlaczego ciąg znaków ma być inny niż inne zmienne obiekty, jeśli chodzi o klucz skrótu? Czy istnieje przypadek użycia, w którym ta specyfikacja staje się przydatna? Jakie inne konsekwencje ma ta specyfikacja?
W rzeczywistości mam przypadek użycia, w którym może być przydatny brak takiej specjalnej specyfikacji ciągów. To znaczy czytałem za pomocąyaml
gem ręcznie zapisany plik YAML, który opisuje skrót. klucze mogą być ciągami znaków i chciałbym pozwolić na niewrażliwość na wielkość liter w oryginalnym pliku YAML. Kiedy czytam plik, mogę uzyskać taki skrót:h = {"foo" => :foo, "Bar" => :bar, "BAZ" => :baz}
I chcę normalizować klucze do małych liter, aby to uzyskać:
h = {"foo" => :foo, "bar" => :bar, "baz" => :baz}
robiąc coś takiego:
h.keys.each(&:downcase!)
ale zwraca błąd z powodów wyjaśnionych powyżej.