0
votes

I have run into this construction:

Enumerator.new(&:map)

and couldn't figure out how I can use it.

For sure this is valid code and it returns the enumerator, but it doesn't have any collection to enumerate over.

How to feed a collection to this enumerator?

1
I’m not sure why you’d be doing this. Collections nearly always extend Enumerator, which provides each, map, collect, select etc. I’m not sure what you’re trying to do with this. - AJFaraday
You may find the ruby documents helpful: ruby-doc.org/core-2.6/Enumerator.html - AJFaraday
@AJFaraday Close, I guess you mean that collections nearly always include Enumerable not Enumerator. They are converted into enumerators most of the time when calling certain methods without blocks. Like each, map and a lot of others. - 3limin4t0r

1 Answers

2
votes

With the current setup you can't pass any collection to it. You can't change the collection of the enumerator once instantiated.

The current code only works because is block is not instantly executed, therefore you see the error when you try to start iterating (or retrieving items).

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

This is because Enumerator::new yields a Enumerator::Yielder which doesn't has the method map.

The above could also be written as:

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

If you would like to create an enumerator from a collection the easiest way is to call each without block. Other methods like map also create enumerators without block given.

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

If you for some reason still want to create the enumerator by hand it could look like this:

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

If the intent was to preselect a method of iterating before you receive the collection, you can do so in the following manner:

# 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)