In computer science, a generator is a special routine that can be used to control the iteration behaviour of a
loop. A generator is very similar to a function that returns an array, in that a generator
has parameters, can be called, and generates a sequence of values. However, instead of building an array containing all the
values and returning them all at once, a generator yields the values one at a time, which
requires less memory and allows the caller to get started processing the first few values immediately. Therefore,
lazy evaluation can be used in the implementation of generators in certain cases.
However, generators are not referentially transparent. In short, a generator
looks like a function but behaves like an iterator.
History
Generators first appeared in CLU (1975)[1] and are now available in Python[2],
C#, and JavaScript[3]. (In CLU and C#, generators are called iterators.) Generators are also a
prominent feature in a string manipulation language, Icon.
Uses
Generators are usually invoked inside loops. The first time that a generator
invocation is reached in a loop, an iterator object is created that
encapsulates the state of the generator routine at its beginning, with arguments bound to the corresponding parameters. The generator's body is then executed in the context of that iterator until a
special yield action is encountered; at that time, the value provided with the yield action is used as the value of
the invocation expression. The next time the same generator invocation is reached in a subsequent iteration, the execution of the
generator's body is resumed after the yield action, until yet another yield action is encountered. In addition to
the yield action, execution of the generator body can also be terminated by a finish action, at which time the
innermost loop enclosing the generator invocation is terminated.
Because generators compute their yielded values only on demand, they are useful for representing sequences that are expensive
to compute, or even infinite.
A pseudorandom number generator is an example of a generator.
In the presence of generators, loop constructs of a language can be reduced into a single loop ... end loop construct; all the
usual loop constructs can then be comfortably simulated by using suitable generators in the right way.
Python
An example Python generator:
<source lang="python"> def countfrom(n):
while True:
yield n
n += 1
- Example use: printing out the integers from 10 to 20.
- Note that this iteration terminates normally, despite countfrom() being
- written as an infinite loop.
for i in countfrom(10):
if i <= 20:
print i
else:
break
- Another generator, which produces prime numbers indefinitely as needed.
def primes():
n = 2
p = []
while True:
if not any( [n % f == 0 for f in p] ):
yield n
p.append( n )
n += 1
>>> f = primes() >>> f.next() 2 >>> f.next() 3 >>> f.next() 5 >>> f.next() 7
</source>
This example works in Python <= 2.5 and uses the any() function from the numpy
module.
In Python, a generator can be thought of as an iterator that contains a frozen stack
frame. Whenever the iterator's next() method is called, Python resumes the frozen frame, which executes
normally until the next yield statement is reached. The generator's frame is then frozen again, and the yielded
value is returned to the caller.
Generators can be implemented in terms of more expressive control flow constructs, such
as coroutines or first-class continuations.[4]
C#
An example C# 2.0 generator:
<source lang="csharp"> // Method that takes an iterable input (possibly an array) // and returns all even numbers.
public static IEnumerable<int> GetEven(IEnumerable<int> numbers) {
foreach (int i in numbers)
{
if ((i % 2) == 0)
{
yield return i;
}
}
} </source>
You may even use multiple yield return statements and the compiler is smart enough to return them in order on each
iteration:
<source lang="csharp"> public class CityCollection : IEnumerable<string> {
public IEnumerator<string> GetEnumerator()
{
yield return "New York";
yield return "Paris";
yield return "London";
}
} </source>
Both of these examples utilise Generics, but this is not required. To use the yield keyword, you must using at least C#
version 2.0. The current version of the C# compiler at this time is 3.5 and is currently in beta.
C++
Defines a generator (implemented as a function object) that counts from 10 up, and we invoke the generator 11 times and print
the results. <source lang="cpp">
- include <iostream>
- include <iterator>
- include <algorithm>
class countfrom { private:
int count;
public:
countfrom(int n) : count(n) {}
int operator()() { return count++; }
};
int main() {
std::generate_n(std::ostream_iterator<int>(std::cout, "\n"), 11, countfrom(10));
return 0;
} </source>
PHP
In PHP, especially when working with MySQL databases, it is often useful to use the built-in function mysql_fetch_array, which
is a generator.
<source lang="php">
$sql = 'SELECT * FROM `users` ORDER BY `user_id` DESC LIMIT 10';
$res = mysql_query( $sql );
// this generator will keep returning data, satisfying the while condition
// as long as there is something new to return, or false when there is no
// more data to return.
// Keep in mind that the equals sign is not a comparison operator, but
// an assignment operator
while ( $row = mysql_fetch_array( $res ) ) {
// process $row
}
</source>
Other Implementations
Since Java does not have continuation or functionality out of the box, an attempt to implement the concept was made, using a
bytecode manipulator (specifically, WebObject's ASM) and
the new Java 5 feature of VM Instrumentation. The code was made public here.
Example of using it:
<source lang="java"> public static Iterable countFrom(final int n) {
return new Yielder() {
protected void yieldNextCore() {
int times = n;
while (times-- > 0) {
yieldReturn(times);
}
}
};
} </source>
See also
- List comprehension for another construct that generates a sequence of values
- Iterator for the concept of producing a list one element at a time
- Lazy evaluation for producing values when needed
- Corecursion for potentially infinite data by recursion instead of yield
- Coroutine for even more generalization from subroutine
- Continuation for generalization of control flow
References
- ^ Liskov, Barbara (April 1992).
A History of
CLU (pdf).
- ^ Python Enhancement Proposals: PEP 255: Simple Generators, PEP 289: Generator Expressions, PEP 342: Coroutines via Enhanced
Generators
- ^ New In JavaScript
1.7. Retrieved on 2006-10-10.
- ^ Kiselyov, Oleg (January 2004). General ways to traverse collections
in Scheme.
- Stephan Murer, Stephen Omohundro, David Stoutamire and Clemens Szyperski: Iteration
abstraction in Sather. ACM Transactions on Programming Languages and Systems, 18(1):1-15 (1996) [1][[Category:Articles
with example C++ code]]
This entry is from Wikipedia, the leading user-contributed encyclopedia. It may not have been reviewed by professional editors (see full disclaimer)