# Enumerators and generators

**URL:** <https://www.ruby-forum.com/t/enumerators-and-generators/191993>\
**Category:** Ruby\
**Created:** [July 22, 2010, 3:21am UTC](https://www.ruby-forum.com/t/enumerators-and-generators/191993 "2010-07-22T03:21:24Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![Hal\_F](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/h/6bbea6/32.png) [@Hal\_F](https://www.ruby-forum.com/u/Hal_F)\
**Post date:** [July 22, 2010, 3:21am UTC](https://www.ruby-forum.com/t/enumerators-and-generators/191993/1 "2010-07-22T03:21:24Z")

</div>

Hi, all…

I’m trying to grasp when/why one might use a generator instead of  
an enumerator (or vice versa).

I’ve used generators, but enumerators are newer to me.

I’ve heard one person’s take on this (thanks David!) but thought  
I might ask more thoughts…

Thanks,  
Hal F.

---

<div class="post-metadata">

**Author:** ![Hal\_F](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/h/6bbea6/32.png) [@Hal\_F](https://www.ruby-forum.com/u/Hal_F)\
**Post date:** [July 22, 2010, 3:44am UTC](https://www.ruby-forum.com/t/enumerators-and-generators/191993/2 "2010-07-22T03:44:14Z")

</div>

Hello Hal

Generators “externalize” iteration, whereas Enumerator “internalize”  
it (but this docs may have already told you).

Generators can be used to create a “controlled stream” of objects,  
that you can operate as you where using a remove control: go to the  
next (Generator#next), give me the position (Generator#pos), return to  
the beginning (Generator#rewind), …

Enumerator offers methods to iterate through the entire stream, like  
iterate using a windows of size X (Enumerator#each\_cons), iterate  
using slices from the stream (Enumerator#each\_slide), …

They are quite different in use, although both are usable to iterate  
over data.

---

<div class="post-metadata">

**Author:** ![Hal\_F](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/h/6bbea6/32.png) [@Hal\_F](https://www.ruby-forum.com/u/Hal_F)\
**Post date:** [July 22, 2010, 9:55am UTC](https://www.ruby-forum.com/t/enumerators-and-generators/191993/3 "2010-07-22T09:55:55Z")

</div>

2010/7/22 Hal F. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid):

> I’m trying to grasp when/why one might use a generator instead of  
> an enumerator (or vice versa).

It seems the alternative is Generator vs. Enumerable rather than  
Generator vs. Enumerator. Enumerator is rather a special form of  
Enumerable which allows to do some things more efficiently because it  
delays the iteration. E.g.

# traditional one liner style: needs much memory:

matches = File.readlines(“foo”).select {|line| /keyword/ =~ line}

# Enumerator: only memory for the

matches = File.to\_enum(:foreach, “foo”).select {|line| /keyword/ =~  
line}

# Same in 1.9 with implicit Enumerator creation

matches = File.foreach(“foo”).select {|line| /keyword/ =~ line}

It’s a convenient replacement for the equally efficient (memory wise):

matches = []

File.foreach “foo” do |line|  
matches \<\< line if /keyword/ =~ line  
end

Generator is a completely different iteration style as Ricardo  
explained.

Kind regards

robert

---

<div class="post-metadata">

**Author:** ![Hal\_F](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/h/6bbea6/32.png) [@Hal\_F](https://www.ruby-forum.com/u/Hal_F)\
**Post date:** [July 22, 2010, 3:09pm UTC](https://www.ruby-forum.com/t/enumerators-and-generators/191993/4 "2010-07-22T15:09:48Z")

</div>

On Thu, Jul 22, 2010 at 07:11, David A. Black [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid)  
wrote:

> > that you can operate as you where using a remove control: go to the  
> > next (Generator#next), give me the position (Generator#pos), return to  
> > the beginning (Generator#rewind), …
> 
> Enumerators have #next and #rewind too, though (though not #pos). In  
> 1.9, as far as I can tell, the generator.rb library has been removed,

I wasn’t aware of it in 1.9. Good to now 🙂

---

<div class="post-metadata">

**Author:** ![Hal\_F](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/h/6bbea6/32.png) [@Hal\_F](https://www.ruby-forum.com/u/Hal_F)\
**Post date:** [July 22, 2010, 12:11pm UTC](https://www.ruby-forum.com/t/enumerators-and-generators/191993/5 "2010-07-22T12:11:46Z")

</div>

Hi –

On Thu, 22 Jul 2010, Ricardo Panaggio wrote:

> Hello Hal
> 
> Generators “externalize” iteration, whereas Enumerator “internalize”  
> it (but this docs may have already told you).
> 
> Generators can be used to create a “controlled stream” of objects,  
> that you can operate as you where using a remove control: go to the  
> next (Generator#next), give me the position (Generator#pos), return to  
> the beginning (Generator#rewind), …

Enumerators have #next and #rewind too, though (though not #pos). In  
1.9, as far as I can tell, the generator.rb library has been removed,  
and Generator is now a class inside Enumerator. An Enumerator::Generator  
is created automatically, for the use of the enumerator, if you create  
an enumerator with a block. Also, these Generators don’t have #next and  
friends; that’s available via the enumerator. (I’m not sure what  
happened to #pos.)

As I understand it, the main thing about generators is that “controlled  
stream” thing, where you can roll your own sense of iteration, rather  
than just piggy-backing on what some enumerable object with its own  
ideas about iteration thinks. Here’s a (very contrived) 1.9 example:

[dblack@ruby-versions ~]$ cat e.rb  
message = nil

g = Enumerator::Generator.new do |yielder|  
yielder \<\< “Hi.”  
puts “I’ve been told to #{message}.”  
case message  
when “leave”  
yielder \<\< “Bye.”  
when “stay”  
yielder \<\< “I’m still here!”  
end  
end

e = Enumerator.new(g)

puts e.next  
message = “stay”  
puts e.next

e.rewind

puts e.next  
message = “leave”  
puts e.next

[dblack@ruby-versions ~]$ ruby e.rb  
Hi.  
I’ve been told to stay.  
I’m still here!  
Hi.  
I’ve been told to leave.  
Bye.

David

–  
David A. Black, Senior Developer, Cyrus Innovation Inc.

The Ruby training with Black/Brown/McAnally  
Compleat Philadelphia, PA, October 1-2, 2010  
Rubyist [http://www.compleatrubyist.com](http://www.compleatrubyist.com)

---

<div class="post-metadata">

**Author:** ![Hal\_F](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/h/6bbea6/32.png) [@Hal\_F](https://www.ruby-forum.com/u/Hal_F)\
**Post date:** [July 22, 2010, 7:35pm UTC](https://www.ruby-forum.com/t/enumerators-and-generators/191993/6 "2010-07-22T19:35:02Z")

</div>

Hi –

On Fri, 23 Jul 2010, Hal F. wrote:

> My next questions then are:
> 
> 1. Does Enumerator::Generator have all the functionality of the  
> old generator.rb, just (it seems to me) a different usage?

No; it doesn’t have #next or #rewind, but enumerators  
(which can easily/transparently wrap generators) do. Neither of them  
appears to have #pos, unless it’s available in some other way that I  
haven’t spotted. (I’m writing this in haste and without benefit of irb,  
so I’m not digging further right now.)

> 1. In David’s example, is “yielder” simply an array of objects? Do  
> we know or care? (If so, I’d be tempted to call it “list” because  
> “yielder” reminds of the keyword yield which I suppose is unrelated  
> here.)

It’s actually an Enumerator::Yielder object, which I think only exists  
for the purpose of being the receptacle for the objects to be yielded by  
the generator.

David

–  
David A. Black, Senior Developer, Cyrus Innovation Inc.

The Ruby training with Black/Brown/McAnally  
Compleat Philadelphia, PA, October 1-2, 2010  
Rubyist [http://www.compleatrubyist.com](http://www.compleatrubyist.com)

---

<div class="post-metadata">

**Author:** ![Hal\_F](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/h/6bbea6/32.png) [@Hal\_F](https://www.ruby-forum.com/u/Hal_F)\
**Post date:** [July 22, 2010, 9:29pm UTC](https://www.ruby-forum.com/t/enumerators-and-generators/191993/7 "2010-07-22T21:29:22Z")

</div>

Hal F. wrote:

> Hi, all…
> 
> I’m trying to grasp when/why one might use a generator instead of  
> an enumerator (or vice versa).
> 
> I’ve used generators, but enumerators are newer to me.

Basically what was a Generator in 1.8 is now an enumerator in 1.9, and  
faster.

[http://wiki.github.com/rdp/ruby\_tutorials\_core/enumerator](http://wiki.github.com/rdp/ruby_tutorials_core/enumerator)

Cheers!  
-r

---

<div class="post-metadata">

**Author:** ![Hal\_F](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/h/6bbea6/32.png) [@Hal\_F](https://www.ruby-forum.com/u/Hal_F)\
**Post date:** [July 22, 2010, 6:28pm UTC](https://www.ruby-forum.com/t/enumerators-and-generators/191993/8 "2010-07-22T18:28:52Z")

</div>

My next questions then are:

1. Does Enumerator::Generator have all the functionality of the  
old generator.rb, just (it seems to me) a different usage?

2. In David’s example, is “yielder” simply an array of objects? Do  
we know or care? (If so, I’d be tempted to call it “list” because  
“yielder” reminds of the keyword yield which I suppose is unrelated  
here.)

Hal

On Thu, Jul 22, 2010 at 7:59 AM, Ricardo Panaggio \<
