В коде направляющих люди склонны использовать метод Enumerable#inject для создания хешей, как это:
somme_enum.inject({}) do |hash, element|
hash[element.foo] = element.bar
hash
end
В то время как это, кажется, стало общей идиомой, делает любой видит преимущество перед "наивной" версией, которая пошла бы как:
hash = {}
some_enum.each { |element| hash[element.foo] = element.bar }
Единственное преимущество я вижу первую версию, состоит в том, что Вы делаете это в закрытом блоке, и Вы (явно) не инициализируете хеш. Иначе это злоупотребляет методом неожиданным способом, более твердо понять и тяжелее читать. Итак, почему это настолько популярно?
Красота в глазах смотрящего. Те, у кого есть некоторый опыт функционального программирования, вероятно, предпочтут метод на основе inject
(как и я), потому что он имеет ту же семантику, что и функция высшего порядка fold
, которая - это распространенный способ вычисления одного результата для нескольких входных данных. Если вы понимаете inject
, значит, вы должны понимать, что функция используется по назначению.
В качестве одной из причин, почему этот подход кажется лучше (на мой взгляд), рассмотрим лексическую область видимости переменной hash
. В методе на основе inject
хэш
существует только в теле блока.В методе на основе каждый
хэш-переменная
внутри блока должна согласовываться с некоторым контекстом выполнения, определенным вне блока. Хотите определить другой хеш в той же функции? Используя метод inject
, можно вырезать и вставить код на основе inject
и использовать его напрямую, и он почти наверняка не внесет ошибок (игнорируя, следует ли использовать C&P во время редактирования - люди делают). Используя метод each
, вам нужно выполнить C&P код и переименовать переменную hash
в любое имя, которое вы хотите использовать - дополнительный шаг означает, что это более подвержено ошибкам.
Я думаю, это связано с тем, что люди не до конца понимают, когда нужно использовать reduce. Я согласен с вами, каждый из них - это то, как должно быть