Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use an enumerator

In the Ruby Array Class documentation, I often find:

If no block is given, an enumerator is returned instead.

Why would I not pass a block to #map? What would be the use of my doing just:

[1,2,3,4].map

instead of doing:

[1,2,3,4].map{ |e| e * 10 } # => [10, 20, 30, 40]

Can someone show me a very practical example of using this enumerator?

like image 879
mjnissim Avatar asked Dec 05 '13 08:12

mjnissim


People also ask

Why do we use enumeration?

Enumerations make for clearer and more readable code, particularly when meaningful names are used. The benefits of using enumerations include: Reduces errors caused by transposing or mistyping numbers. Makes it easy to change values in the future.

What is enumeration explain with example?

An enumerated type is a type whose legal values consist of a fixed set of constants. Common examples include compass directions, which take the values North, South, East and West and days of the week, which take the values Sunday, Monday, Tuesday, Wednesday, Thursday, Friday, and Saturday.

What is the use of enum in C++?

In C++ programming, enum or enumeration is a data type consisting of named values like elements, members, etc., that represent integral constants. It provides a way to define and group integral constants. It also makes the code easy to maintain and less complex.

What can an enum include?

An enum class can include methods and fields just like regular classes. When we create an enum class, the compiler will create instances (objects) of each enum constants. Also, all enum constant is always public static final by default.


2 Answers

Good question.

What if we want to do multiple things with the enumerator that is created? We don't want to process it now, because it means we may need to create another later?

my_enum = %w[now is the time for all good elves to get to work].map # => #<Enumerator: ["now", "is", "the", "time", "for", "all", "good", "elves", "to", "get", "to", "work"]:map>

my_enum.each(&:upcase) # => ["NOW", "IS", "THE", "TIME", "FOR", "ALL", "GOOD", "ELVES", "TO", "GET", "TO", "WORK"]
my_enum.each(&:capitalize) # => ["Now", "Is", "The", "Time", "For", "All", "Good", "Elves", "To", "Get", "To", "Work"]
like image 177
vgoff Avatar answered Oct 04 '22 08:10

vgoff


The main distinction between an Enumerator and most other data structures in the Ruby core library (Array, Hash) and standard library (Set, SortedSet) is that an Enumerator can be infinite. You cannot have an Array of all even numbers or a stream of zeroes or all prime numbers, but you can definitely have such an Enumerator:

evens = Enumerator.new do |y|
  i = -2
  y << i += 2 while true
end

evens.take(10)
# => [0, 2, 4, 6, 8, 10, 12, 14, 16, 18]

zeroes = [0].cycle

zeroes.take(10)
# => [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]

So, what can you do with such an Enumerator? Well, three things, basically.

  1. Enumerator mixes in Enumerable. Therefore, you can use all Enumerable methods such as map, inject, all?, any?, none?, select, reject and so forth. Just be aware that an Enumerator may be infinite whereas map returns an Array, so trying to map an infinite Enumerator may create an infinitely large Array and take an infinite amount of time.

  2. There are wrapping methods which somehow "enrich" an Enumerator and return a new Enumerator. For example, Enumerator#with_index adds a "loop counter" to the block and Enumerator#with_object adds a memo object.

  3. You can use an Enumerator just like you would use it in other languages for external iteration by using the Enumerator#next method which will give you either the next value (and move the Enumerator forward) or raise a StopIteration exception if the Enumerator is finite and you have reached the end.

Eg., an infinite range: (1..1.0/0)

like image 36
Jörg W Mittag Avatar answered Oct 04 '22 08:10

Jörg W Mittag