рубиновое хеширование (гранит) - PullRequest
8 голосов
/ 01 октября 2009

Вот хитрый трюк для включения автовификации хэша в ruby ​​(взятый из фасетов):

  # File lib/core/facets/hash/autonew.rb, line 19
  def self.autonew(*args)
    leet = lambda { |hsh, key| hsh[key] = new( &leet ) }
    new(*args,&leet)
  end

Хотя это работает (конечно), меня действительно расстраивает то, что я не могу понять, как эти два лайнера делают то, что делают.

leet ставится как значение по умолчанию. Так что тогда простой доступ к h['new_key'] каким-то образом вызывает его и создает 'new_key' => {}

Теперь я ожидаю, что h['new_key'] вернет объект значения по умолчанию, а не оценит его. То есть 'new_key' => {} не создается автоматически. Так как же на самом деле вызывается leet? Особенно с двумя параметрами?

Ответы [ 3 ]

18 голосов
/ 01 октября 2009

Стандартный новый метод для Hash принимает блок. Этот блок вызывается в случае попытки доступа к ключу в хэше, который не существует. Блок передает сам хэш и ключ, который был запрошен (два параметра), и должен возвращать значение, которое должно быть возвращено для запрошенного ключа.

Вы заметите, что leet лямбда делает 2 вещи. Он возвращает новый Hash с leet в качестве блока для обработки значений по умолчанию. Это поведение, которое позволяет autonew работать для хэшей произвольной глубины. Он также назначает этот новый хэш на hsh[key], чтобы в следующий раз, когда вы запросите тот же ключ, вы получили существующий хэш, а не создаваемый новый.

8 голосов
/ 21 октября 2009

Стоит также отметить, что этот код можно превратить в однострочник следующим образом:

def self.autonew(*args)
  new(*args){|hsh, key| hsh[key] = Hash.new(&hsh.default_proc) }
end

Вызов Hash # default_proc возвращает proc, который использовался для создания родителя, поэтому у нас есть хорошая рекурсивная настройка.

Я говорю о подобном случае с этим в моем блоге.

0 голосов
/ 26 июля 2013

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

Если вы ищете что-то, что еще не существует, вы получите нулевое значение (или другое значение или исключение, если вы предпочитаете), не создавая ничего путем поиска. Может также добавляться в конец массивов.

Вы можете выбрать автовивификацию хешей или массивов для целочисленных ключей (но только один раз для всей структуры).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...