Я попытался реализовать сокращение с помощью фигурных скобок, но не смог заставить его работать. Предполагается, что функция принимает массив слов (символов или строк) и создает хэш, где ключи - это слова, а значения - длина слов. Вот моя попытка фигурных скобок:
def find_word_lengths(word_list)
word_list.reduce(Hash.new(0)) { |hash,word| hash[word] = word.length}
end
Я все время получаю сообщение об ошибке undefined method '[]=' for 3:Integer
.
Когда я использую do
вместо фигурных скобок, он работает, но только когда я возвращаю аккумулятор в конце блока сокращения.
def find_word_lengths(word_list)
word_list.reduce(Hash.new(0)) do |hash,word|
hash[word] = word.length
hash
end
end
Я понимаю, почему второй работает, но не понимаю, почему первый нет. Насколько я понимаю, сокращение состоит в том, что он неявно возвращает аккумулятор после прохождения через массив, который он вызвал. По крайней мере, когда я пишу вызов функции уменьшения, который сводится к числу, он автоматически возвращает сумму
my_numbers = [5, 6, 7, 8]
my_numbers.reduce(1000) { |sum, number| sum + number }
#=>1026
По-разному ли reduce ведет себя в зависимости от типа аккумулятора?
2 ответа
Аккумулятор НЕ возвращается неявно. Это предположение, которое нарушает весь ваш анализ.
Если вы внимательно прочитаете, это указано в документах:
... В любом случае результат становится новым значением для памятки . ..
Это говорит о том, что результат выполнения блока, фигурные скобки или do / end , становится новым значением для memo в следующем раунде.
Таким образом, фигурные скобки и do / end работают одинаково, просто вы предполагали, что памятка была возвращена неявно, а это не так.
Если вы проанализируете свой код сейчас с этими новыми знаниями, вы должны надеяться понять, почему некоторые примеры работают, а другие нет.
Помните, что последняя инструкция внутри блока будет значением памятки на следующей итерации.
В первом примере вы возвращаете результат присвоения word.length
hash[word]
, то есть самого word.length
. Таким образом, вторая итерация цикла получит длину первого слова вашего word_list
в качестве аргумента.
Во втором примере вы явно возвращаете хэш в блоке (который затем работает).
Эквивалент однострочной версии с фигурными скобками вашей рабочей многострочной версии:
word_list.reduce(Hash.new(0)) { |hash, word| hash[word] = word.length; hash }
Вместо использования reduce
вы также можете использовать вместо него each_with_object
, который всегда будет возвращать исходный объект для каждой итерации:
word_list.each_with_object(Hash.new(0)) { |hash, word| hash[word] = word.length }
Похожие вопросы
Новые вопросы
ruby
Ruby - это многоплатформенный динамический объектно-ориентированный интерпретируемый язык с открытым исходным кодом. Тег [ruby] предназначен для вопросов, связанных с языком Ruby, включая его синтаксис и его библиотеки. Вопросы Ruby on Rails должны быть помечены [ruby-on-rails].
do ... end
.