Почему Array#each возвращает массив с одинаковыми элементами?

Я изучаю детали того, как each работает в ruby, и попробовал следующую строку кода:

p [1,2,3,4,5].each { |element| el }

И в результате получается массив

[1,2,3,4,5]

Но я не думаю, что полностью понимаю, почему. Почему возвращаемое значение each является одним и тем же массивом? Разве каждый не просто предоставляет метод для итерации? Или метод each просто возвращает исходное значение?


person Jeff Storey    schedule 22.07.2012    source источник
comment
Ruby API docs говорит each {|item| block } → ary, поэтому да each{block} метод класса Array возвращает self   -  person mask8    schedule 22.07.2012
comment
Причина скорее в удобстве. По сути, это бесплатная операция для Ruby по возврату исходного массива (иначе он вернул бы nil). В качестве бонуса он позволяет вам связывать методы для дальнейшей работы с массивом, если хотите.   -  person Casper    schedule 22.07.2012
comment
Небольшой момент: если блока нет, [1,2,3].each возвращает [1,2,3].to_enum (по крайней мере, в Ruby 2.0).   -  person Cary Swoveland    schedule 14.08.2013


Ответы (4)


Array#each возвращает объект [массив], для которого он был вызван. : результат блока отбрасывается. Таким образом, если в исходном массиве нет побочных эффектов icky, то ничего не изменится.

Возможно, вы имеете в виду использовать map?

p [1,2,3,4,5].map { |i| i*i }
person Community    schedule 22.07.2012
comment
Я не пытался использовать карту, просто задавался вопросом, почему возвращаемое значение было одним и тем же массивом. Но вы подтвердили, что он просто возвращает тот же объект - person Jeff Storey; 22.07.2012

Массив#каждый

Блочная форма Array#each возвращает исходный объект Array. Обычно вы используете #each, когда хотите что-то сделать с каждым элементом массива внутри блока. Например:

[1, 2, 3, 4, 5].each { |element| puts element }

Это распечатает каждый элемент, но вернет исходный массив. Вы можете проверить это с помощью:

array = [1, 2, 3, 4, 5]
array.each { |element| element }.object_id === array.object_id
=> true

Массив#карта

Если вы хотите вернуть новый массив, используйте Array#map или один из его синонимов. Блочная форма #map возвращает другой объект Array. Например:

array.object_id
=> 25659920
array.map { |element| element }.object_id
=> 20546920
array.map { |element| element }.object_id === array.object_id
=> false

Как правило, вы захотите использовать #map, когда хотите работать с модифицированной версией исходного массива, оставляя оригинал без изменений.

person Todd A. Jacobs    schedule 22.07.2012

Все методы что-то возвращают. Даже если это просто объект nil, он что-то возвращает.

Он также может возвращать исходный объект, а не возвращать nil.

person Andrew Grimm    schedule 23.07.2012
comment
Да, я просто ожидал, что это будет Nil, хотя я должен был прочитать документы немного внимательнее. - person Jeff Storey; 24.07.2012

Если вы хотите по какой-то причине подавить вывод (например, отладку в консоли), вот как вы можете добиться этого

  [1,2,3,4,5].each do |nr|
    puts nr.inspect
  end;nil
person Markus Andreas    schedule 21.11.2018
comment
OMG end;nil ЭТО ТО, ЧТО Я ИСКАЛ ВСЮ СВОЮ ЖИЗНЬ!!! - person Andrew; 15.06.2021