Being a declarative language, ruby
provides many functions which make
developer lives easier. One of those functions is Enumerable#inject
.
This function iterates through elements of an Enumerable
by applying an
operation represented by a block (or a symbol which represents a method
defined on elements of the enumerable).
Example:
(1..10).inject(:+)
# returns 55
The above function calls +
method on the accumulator and the next element
of the list, which further sets it to the next iteration’s accumulator. Hence,
we get the sum for first 10 numbers, 55
.
Lazy
with INFINITY
stream
In order to call the inject with a stream of integers, we can use
Float::INFINITY
with Enumerator::Lazy
.
(1..Float::INFINITY).lazy.first(10).inject(:+)
This allows us to call first
with an integer which gets the first few
elements from the infinite stream of integers, which forms an array, which then
applies the inject operation on it’s elements.
For Fun: Enumerator::Lazy#inject/3
Another way to accomplsh the above functionality is by creating a method
inject
which is called with three arguments:
acc
: Initial value of the accumulator.
first
: First first
number of elements to take from the lazy.
&block
: Operation represented by a block.
# Opening up Enumerator::Lazy class
class Enumerator::Lazy
def inject(acc, first, &block)
@acc = acc
Lazy.new(self) do |yielder, *result|
@acc = yield [*result, @acc]
yielder << @acc
end.first(first).last
end
end
(1..Float::INFINITY).lazy.inject(0, 10) { |a, b| a + b }
# returns 55
This defines a method, inject
for Enumerator::Lazy
, which allows us to call
inject
with the first
argument.
This functionality can be extended to other Enumerable
operations like
each
and each_with_index