Почему строковый ключ для хэша заморожен?
СогласноСпецификациястроки, используемые в качестве ключа для хэша, дублируются и замораживаются. Другие изменяемые объекты, кажется, не имеют такого особого рассмотрения. Например, с ключом массива возможно следующее.
a = [0]
h = {a => :a}
h.keys.first[0] = 1
h # => {[1] => :a}
h[[1]] # => nil
h.rehash
h[[1]] # => :a
С другой стороны, подобное нельзя сделать с помощью строкового ключа.
s = "a"
h = {s => :s}
h.keys.first.upcase! # => RuntimeError: can't modify frozen String
Почему строка разработана так, чтобы отличаться от других изменяемых объектов, когда речь идет о хэш-ключе? Есть ли какой-либо вариант использования, где эта спецификация становится полезной? Какие еще последствия имеет эта спецификация?
У меня фактически есть случай использования, где отсутствие такой специальной спецификации о строках может быть полезным. То есть я читаю сyaml
gem вручную написанный файл YAML, который описывает хэш. ключи могут быть строками, и я хотел бы разрешить регистронезависимость в исходном файле YAML. Когда я читаю файл, я могу получить хеш-код:h = {"foo" => :foo, "Bar" => :bar, "BAZ" => :baz}
И я хочу нормализовать ключи в нижнем регистре, чтобы получить это:
h = {"foo" => :foo, "bar" => :bar, "baz" => :baz}
делая что-то вроде этого:
h.keys.each(&:downcase!)
но это возвращает ошибку по причине, описанной выше.