Почему методы из Enumerable возвращают Enumerator?

Многие методы Ruby Enumerable возвращают Enumerator, если вы не передаете блок.

Пример:

array = [1,2,3]
array.each.class
# => Enumerator
array.each { |n| n+10 }.class
# => Array

Что является причиной этого? Почему бы им просто не вернуть nil или что-то еще, сигнализирующее о том, что блок не был предоставлен.


person SharkLaser    schedule 26.10.2014    source источник
comment
Непонятно, что вы подразумеваете под методом, который не может each сам по себе.   -  person sawa    schedule 26.10.2014
comment
Спасибо. Я почистил описание.   -  person SharkLaser    schedule 26.10.2014


Ответы (1)


Счетчики дают вам контроль над итерацией

Среди прочего, перечислители дают вам контроль над когда вы выполняете итерацию по объекту. Иногда вам не нужно, чтобы итерация происходила сейчас, поэтому вы сохраняете Enumerator для последующего использования, а не сразу передаете результаты в блок. В других случаях вам может понадобиться более детальный контроль над самим процессом итерации.

Один из самых полезных (и малоиспользуемых) методов — Перечислимое#ленивый. Вместо того, чтобы сразу повторять миллион целых чисел из диапазона, вы можете брать по одному, когда вам это нужно. Например:

enum = (1..1_000_000).lazy
enum.next #=> 1
enum.next #=> 2
enum.peek #=> 3
enum.next #=> 3

Это имеет очевидные последствия для производительности. Ваш пробег может отличаться.

person Todd A. Jacobs    schedule 26.10.2014
comment
Хороший ответ. Еще одним преимуществом является то, что перечислители можно передавать методам в качестве аргументов для выполнения действий с использованием next, peek и т. д., не зная, что такое перечислитель (например, arr.select или arr.reject). Перечислители иногда также полезны для упрощения неудобного кода. Например, если вы хотите, чтобы значение чередовалось между true и false, вы можете просто написать v = [true,false].cycle, а затем v.next => true; v.next => false; v.next => true.... - person Cary Swoveland; 26.10.2014