How can I get a lazy array in Ruby?
In Haskell, I can talk about [1..]
, which is an infinite list, lazily generated as needed. I can also do things like iterate (+2) 0
, which applies whatever function I give it to generate a lazy list. In this case, it would give me all even numbers.
I'm sure I can do such things in Ruby, but can't seem to work out how.
Enumerator::Lazy is a special type of Enumerator , that allows constructing chains of operations without evaluating them immediately, and evaluating values on as-needed basis. In order to do so it redefines most of Enumerable methods so that they just construct another lazy enumerator.
Lazy enumeration means that an expression is only processed when we are working with the result. There are languages that are lazy by default, like Haskell, and many others are implementing a way to lazily evaluate expressions.
This can be done in a few ways in Ruby. The first is the plus operator. This will append one array to the end of another, creating a third array with the elements of both. Alternatively, use the concat method (the + operator and concat method are functionally equivalent).
The first() is an inbuilt method in Ruby returns an array of first X elements. If X is not mentioned, it returns the first element only. Syntax: range1.first(X) Parameters: The function accepts X which is the number of elements from the beginning. Return Value: It returns an array of first X elements.
With Ruby 1.9 you can use the Enumerator class. This is an example from the docs:
fib = Enumerator.new { |y| a = b = 1 loop { y << a a, b = b, a + b } } p fib.take(10) #=> [1, 1, 2, 3, 5, 8, 13, 21, 34, 55]
Also, this is a nice trick:
Infinity = 1.0/0 range = 5..Infinity p range.take(10) #=> [5, 6, 7, 8, 9, 10, 11, 12, 13, 14]
This one only works for consecutive values though.
Recently Enumerable::Lazy has been added to ruby trunk. We'll see it in ruby 2.0. In particular:
a = data.lazy.map(&:split).map(&:reverse)
will not be evaluated immediately.
The result is instance of Enumerable::Lazy, that can be lazy chained any further. If you want to get an actual result - use #to_a
, (#take(n)
#take
is now lazy too, use #to_a
or #force
), etc.
If you want more on this topic and my C patch - see my blog post Ruby 2.0 Enumerable::Lazy
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With