What is the difference between an Iterator and a Generator?
A generator is an implementation of an iterator. It is typically a routine that yields multiple values to its caller as opposed to just one.
In c#
// yield-example.cs
using System;
using System.Collections;
public class List
{
public static IEnumerable Power(int number, int exponent)
{
int counter = 0;
int result = 1;
while (counter++ < exponent)
{
result = result * number;
yield return result;
}
}
static void Main()
{
// Display powers of 2 up to the exponent 8:
foreach (int i in Power(2, 8))
{
Console.Write("{0} ", i);
}
}
}
See Wikipedia's entry
Generators are iterators, but not all iterators are generators.
An iterator is typically something that has a next method to get the next element from a stream. A generator is an iterator that is tied to a function.
For example a generator in python:
def genCountingNumbers():
n = 0
while True:
yield n
n = n + 1
This has the advantage that you don't need to store infinite numbers in memory to iterate over them.
You'd use this as you would any iterator:
for i in genCountingNumbers():
print i
if i > 20: break # Avoid infinite loop
You could also iterate over an array:
for i in ['a', 'b', 'c']:
print i
An iterator is used to iterate over the objects in a collection, be that an array, linked list, tree, hash map, whatever. You've got a bunch of objects and you want to do something with each one of them.
A generator doesn't just return the items from some finite collection of objects. Instead, it generates them on the fly. You could conceptualize it as an iterator over a collection that is created while you are iterating over it and may not have finite size.
For instance, you could have a generator that spits out prime numbers from 2 to infinity. There's no way you could have a collection of "all prime numbers" and iterate over it with an iterator. You need a generator.
Or you could have a generator that takes an integer and yields the factors of that number one at a time. A generator would benefit you here as you could examine the factors one by one without allocating memory for all of the factors upfront. It would also allow you to use them as they are generated rather than having to generate the entire list up front, which might be slower than you like. Here's an example of such a generator in Python:
def factors(n):
for i in xrange(1, n+1):
if n % i == 0:
yield i
for n in factors(1234567890):
print n
If you run this you can see the factors printed as they are calculated. We don't need to actually maintain an entire list of all factors in memory.