2012-02-29 4 views
8

рубин позволяет определить значения по умолчанию для хэшей:Изменение значения по умолчанию хэш

h=Hash.new(['alright']) 
h['meh'] # => ["alright"] 

Присвоение значения проявляющимся при отображении хэш, но модифицированный по умолчанию не делает. Где 'bad'?

h['good']=['fine','dandy'] 
h['bad'].push('unhappy') 
h # => {"good"=>["fine", "dandy"]} 

'bad' показывает, если мы явно спросить.

h['bad'] # => ["alright", "unhappy"] 

Почему измененное значение по умолчанию не отображается при отображении хэша?

+0

Законный вопрос, но это, вероятно, дубликат. –

ответ

11

хэш-функции по умолчанию не делает работайте так, как вы ожидаете. Когда вы говорите h[k], процесс выглядит следующим образом:

  1. Если у нас есть k ключа, возвращает его значение.
  2. Если у нас есть значение по умолчанию для Hash, верните это значение по умолчанию.
  3. Если у нас есть блок для предоставления значений по умолчанию, выполните блок и верните его возвращаемое значение.

Обратите внимание, что (2) и (3) ничего не говорят о вставке k в хэш. Значение по умолчанию, по существу превращает h[k] в этом:

h.has_key?(k) ? h[k] : the_default_value 

Так просто доступ к несуществующему ключу и получить значение по умолчанию обратно не добавят недостающий ключ к Hash.

Кроме того, все формы:

Hash.new([ ... ]) 
# or 
Hash.new({ ... }) 

почти всегда ошибка, как вы будете делить точно такой же массив по умолчанию или хэша для всех значений по умолчанию. Например, если вы сделаете это:

h = Hash.new(['a']) 
h[:k].push('b') 

Тогда h[:i], h[:j] ... все будет возвращаться ['a', 'b'] и это редко, что вы хотите.

Я думаю, что вы ищете block form of the default value:

h = Hash.new { |h, k| h[k] = [ 'alright' ] } 

Это будет делать две вещи:

  1. Доступ к несуществующий ключ будет добавить, что ключ к Hash и она будет иметь предоставленный массив в качестве значения.
  2. Все значения по умолчанию будут различными объектами, поэтому их изменение не изменит остальных.
2

Что случилось, что вы имеете модифицированы по умолчанию значения хэша, по push ИНГАМ «несчастные» на h['bad']. Что вы не сделали сделано на самом деле добавлено «плохо» в хэш, поэтому он не появляется, когда вы проверяете h.

После всего кода вы предоставили, я попытался это:

>> p h['bleh'] 
=> ["allright", "unhappy"] 

Что, безусловно, наводит меня на мысль, что значение по умолчанию изменено. В ответ на ваш вопрос: «Почему измененная по умолчанию не отображаются при отображении хэш?», Вы должны добавить элемент к нему, а не только доступ к нему: значение

>> h['bleh'] # Doesn't add 'bleh' to the hash 
>> p h 
=> {"good"=>["fine", "dandy"]} # See, no extra values 

>> h['bleh'] = h.default # Does add a new key with the default value 
>> p h 
=> {"good"=>["fine", "dandy"], "bleh"=>["allright", "unhappy"]} 
+1

Ничего себе. Я полностью исправляюсь. Но теперь я озадачен тем, что это так. [] - метод для хэш-объекта, который возвращает результат. Зачем посылать push для этого изменения хэша по умолчанию? Время, чтобы начать копать через исходный код ruby ​​... –

+0

Получил его. Объект Hash все еще содержит ссылку на обновляемый массив. Удаление моего ответа. :) –

+1

Я предполагаю, что значением по умолчанию является ссылка на массив, переданный в конструктор Hash. Когда вы нажимаете на это, вы непосредственно изменяете массив, а не создаете копию. Для более простого примера: 'h = Hash.new ('hello'); h ['something'] << 'aaa'; puts h.default' вернет 'helloaaa' –

Смежные вопросы