Ruby 2.7 has added Enumerator#produce to generate Enumerator from any custom data-transformation.
Before
Let’s say we want to print the first 10 numbers of fibonacci series.
The code to achieve this would look like:
result = Enumerator.new do |yielder|
base_1 = 0
base_2 = 1
loop do
yielder.yield base_1
base_1, base_2 = base_2, base_1 + base_2
end
end
result.take(10)
=> [0, 1, 1, 2, 3, 5, 8, 13, 21, 34]As shown above, we need to use loop and yield
in order to achieve the required results.
Enumerator#produce
We can now use Enumerator#produce in Ruby 2.7
to achieve this in a simpler way:
Enumerator.produce([0, 1]) { |base_1, base_2| [base_2, base_1 + base_2] }.take(10).map(&:first)
=> [0, 1, 1, 2, 3, 5, 8, 13, 21, 34]Enumerator.produce(initial, &block), will produce an infinite sequence
where each next element is calculated
by applying block to previous.
initial is the first sequence element.
We can use produce without initial value as well.
Enumerator.produce(&block), will produce an infinite sequence.
The first element of the sequence will be the result of calling
the block with no args.
Example of produce without args:
# Get random date within a month which falls on weekday
Enumerator.produce { Date.today+rand(30) }.detect{ |date| !date.sunday? || !date.saturday? }
=> #<Date: 2019-11-15 ((2458803j,0s,0n),+0s,2299161j)>As illustrated above, produce helps to
produce enumerators with a much cleaner and simpler code.
More information about this feature along with few other examples can be found on Feature #14781.
