Перечислитель без коллекции - PullRequest
0 голосов
/ 16 марта 2020

Я столкнулся с этой конструкцией:

Enumerator.new(&:map)

и не мог понять, как я могу ее использовать.

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

Как передать коллекцию в этот перечислитель?

1 Ответ

2 голосов
/ 16 марта 2020

При текущей настройке вы не можете передать ей любую коллекцию. Вы не можете изменить коллекцию перечислителя после создания экземпляра.

Текущий код работает только потому, что блок выполняется не сразу, поэтому вы видите ошибку, когда пытаетесь начать итерацию (или получение элементов).

enumerator = Enumerator.new(&:map)
enumerator.take(1)
# NoMethodError (undefined method `map' for #<Enumerator::Yielder:0x00000000055b6e90>)

Это потому, что Enumerator::new дает Enumerator::Yielder, который не имеет метода map.

Выше также можно записать как:

enumerator = Enumerator.new { |yielder| yielder.map }

Если вы хотите создать перечислитель из коллекции, проще всего вызвать each без блока. Другие методы, такие как map, также создают перечислители без заданного блока.

enumerator = [1, 2, 3].each
#=> #<Enumerator: [1, 2, 3]:each>

Если по какой-то причине вы все еще хотите создать перечислитель вручную, он может выглядеть следующим образом:

enumerator = Enumerator.new { |yielder| [1, 2, 3].each { |number| yielder << number } }

Если вы хотели предварительно выбрать метод итерации до получения коллекции, вы можете сделать это следующим образом:

# assuming both the collection and block are passed by the user
map = :map.to_proc
result = map.call(collection, &block)

# which is equivalent to
result = collection.map(&block)
...