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

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

Хорошо, это выглядит модно, но это также не дает нам хорошего результата, и это тоже довольно странный результат. Здесь есть две проблемы, давайте попробуем исправить их по очереди. Во-первых, в нашем альтернативном театре слишком много студентов. Фактически, мы могли вызвать любой ключ из нашего хэша и получить тот же результат. В строке 4 мы изменили значение нашего хэша по умолчанию. Поскольку объект массива, который является нашим хеш-значением по умолчанию, создается в круглых скобках, Ruby предоставит ссылку на него в следующий раз, когда он будет использоваться. Следовательно, в строке 4 мы добавляем ученика к этому объекту, а не к конкретной ссылке, связанной только с нашим ключом (здесь option).

Итак, первый подход - передать блок вместо использования скобок.

Таким образом, когда мы дойдем до строки 4, массив, который будет изменяться, будет каждый раз новым: это будет возвращаемое значение нашей процедуры по умолчанию { [] }.

Однако мы видим, что здесь все еще есть проблема. Действительно, наш хеш остается пустым. Причина в том, что когда вы получаете доступ к ключу, вы его не устанавливаете. Таким образом, вы получите доступ к ключам и найдете массивы, а затем отправите какое-то значение в эти массивы, но вы никогда не скажете своему хешу, чтобы установить ключи, где находятся эти массивы. Когда вы повторяете второй раз тот же ключ, он воссоздает новый массив из процедуры по умолчанию. С учетом всего сказанного нам все еще нужно сделать еще один шаг.

При инициализации хеша мы можем дать блоку два аргумента, которые соответствуют хешу и ключу. Это позволяет нам поместить инициализацию внутри нашего хеш-объявления. Я бы сказал, что это немного лучше, чем метод top, поскольку вы можете видеть цель своего хэша во время объявления.

Заключение

Использование значения по умолчанию в классе Ruby Hash - дело непростое. Практическое правило заключается в том, что вы можете использовать его со скобками только для неизменяемых классов, например grades = Hash.new(10). Однако, когда вы используете изменяемые классы, не забудьте установить каждый ключ, используя либо старый метод, показанный первым, либо новый, показанный последним.

Трудно понять, почему разработчики Ruby сделали это, если у вас есть какой-либо пример использования, не стесняйтесь проявить свое творчество в разделе комментариев. Я считаю, что вы можете использовать эту функцию в том, что вы можете улучшить Proc со значениями по умолчанию.

Работа над этой веткой научила меня кое-чему: иногда просто не нужно фантазировать. Использование этих значений по умолчанию может вызвать головную боль там, где в этом нет необходимости. Это очень похоже на этот отрывок из стихов Джейми Завински, который должен знать каждый разработчик:

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

Крошечный бонус

В этом примере показана скрытая функция рубина, которая может вызвать некоторые проблемы. Грамматика a += 1 - это синтаксический сахар для a = a + 1. Это создает новый объект вместо изменения предыдущего. Это причина того, что в нашем предыдущем примере += и << дают действительно разные результаты.

С учетом сказанного, можете ли вы придумать другой способ без проблем написать главную проблему, используя Hash.new([])?

Совет: не изменяйте, а заменяйте!