---
title: "Ruby 2.7 adds Enumerator::Lazy#eager"
description: "Ruby 2.7 adds Enumerator::Lazy#eager"
canonical_url: "https://www.bigbinary.com/blog/ruby-2-7-adds-enumerator-lazy-eager"
markdown_url: "https://www.bigbinary.com/blog/ruby-2-7-adds-enumerator-lazy-eager.md"
---

# Ruby 2.7 adds Enumerator::Lazy#eager

Ruby 2.7 adds Enumerator::Lazy#eager

- Author: Ashik Salman
- Published: March 18, 2020
- Categories: Ruby 2.7, Ruby

Ruby 2.0 introduced
[`Enumerator::Lazy`](https://ruby-doc.org/core-2.7.0/Enumerator/Lazy.html), a
special type of enumerator which helps us in processing chains of operations on
a collection without actually executing it instantly.

By applying
[`Enumerable#lazy`](https://ruby-doc.org/core-2.7.0/Enumerable.html#method-i-lazy)
method on any enumerable object, we can convert that object into
`Enumerator::Lazy` object. The chains of actions on this lazy enumerator will be
evaluated only when it is needed. It helps us in processing operations on large
collections, files and infinite sequences seamlessly.

```ruby
# This line of code will hang and you will have to quit the console by Ctrl+C.
irb> list = (1..Float::INFINITY).select { |i| i%3 == 0 }.reject(&:even?)

# Just adding `lazy`, the above line of code now executes properly
# and returns result without going to infinite loop. Here the chains of
# operations are performed as and when it is needed.
irb> lazy_list = (1..Float::INFINITY).lazy.select { |i| i%3 == 0 }.reject(&:even?)
=> #<Enumerator::Lazy: ...>

irb> lazy_list.first(5)
=> [3, 9, 15, 21, 27]

```

When we chain more operations on `Enumerable#lazy` object, it again returns lazy
object without executing it. So, when we pass lazy objects to any method which
expects a normal enumerable object as an argument, we have to force evaluation
on lazy object by calling
[`to_a`](https://ruby-doc.org/core-2.7.0/Enumerator/Lazy.html#method-i-to_a)
method or it's alias
[`force`](https://ruby-doc.org/core-2.7.0/Enumerator/Lazy.html#method-i-force).

```ruby

# Define a lazy enumerator object.
irb> list = (1..30).lazy.select { |i| i%3 == 0 }.reject(&:even?)
=> #<Enumerator::Lazy: #<Enumerator::Lazy: ... 1..30>:select>:reject>

# The chains of operations will return again a lazy enumerator.
irb> result = list.select { |x| x if x <= 15 }
=> #<Enumerator::Lazy: #<Enumerator::Lazy: ... 1..30>:select>:reject>:map>

# It returns error when we call usual array methods on result.
irb> result.sample
irb> NoMethodError (undefined method `sample'
irb> for #<Enumerator::Lazy:0x00007faab182a5d8>)

irb> result.length
irb> NoMethodError (undefined method `length'
irb> for #<Enumerator::Lazy:0x00007faab182a5d8>)

# We can call the normal array methods on lazy object after forcing
# its actual execution with methods as mentioned above.
irb> result.force.sample
=> 9

irb> result.to_a.length
=> 3

```

The
[`Enumerable#eager`](https://ruby-doc.org/core-2.7.0/Enumerator/Lazy.html#method-i-eager)
method returns a normal enumerator from a lazy enumerator, so that lazy
enumerator object can be passed to any methods which expects a normal enumerable
object as an argument. Also, we can call other usual array methods on the
collection to get desired results.

```ruby

# By adding eager on lazy object, the chains of operations would return
# actual result here. If lazy object is passed to any method, the
# processed result will be received as an argument.
irb> eager_list = (1..30).lazy.select { |i| i%3 == 0 }.reject(&:even?).eager
=> #<Enumerator: #<Enumerator::Lazy: ... 1..30>:select>:reject>:each>

irb> result = eager_list.select { |x| x if x <= 15 }
irb> result.sample
=> 9

irb> result.length
=> 3

```

The same way, we can use `eager` method when we pass lazy enumerator as an
argument to any method which expects a normal enumerator.

```ruby
irb> list = (1..10).lazy.select { |i| i%3 == 0 }.reject(&:even?)
irb> def display(enum)
irb>   enum.map { |x| p x }
irb> end

irb>  display(list)
=> #<Enumerator::Lazy: #<Enumerator::Lazy: ... 1..30>:select>:reject>:map>

irb> eager_list = (1..10).lazy.select { |i| i%3 == 0 }.reject(&:even?).eager
irb> display(eager_list)
=> 3
=> 9

```

Here's the relevant
[commit](https://github.com/ruby/ruby/commit/1d4bd229b898671328c2a942b04f08065c640c28)
and [feature discussion](https://bugs.ruby-lang.org/issues/15901) for this
change.

## Links

- [Human page](https://www.bigbinary.com/blog/ruby-2-7-adds-enumerator-lazy-eager)
