Uses
Generators are usually invoked inside loops.The Icon Programming Language utilizes generators to implement its goal directed evaluation. In Icon, generators can be invoked in contexts outside of the normal looping control structures. 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 correspondingg
can be evaluated to a list l
via l = list(g)
, while in F# the sequence expression seq
evaluates lazily (a generator or sequence) but ... /code> evaluates eagerly (a list).
In the presence of generators, loop constructs of a language – such as for and while – 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. For example, a ranged loop like for x = 1 to 10
can be implemented as iteration through a generator, as in Python's for x in range(1, 10)
. Further, break
can be implemented as sending ''finish'' to the generator and then using continue
in the loop.
Languages providing generators
Generators first appeared in CLU (1975), were a prominent feature in the string manipulation language Icon
An icon () is a religious work of art, most commonly a painting, in the cultures of the Eastern Orthodox, Oriental Orthodox, Catholic Church, Catholic, and Lutheranism, Lutheran churches. The most common subjects include Jesus, Mary, mother of ...
(1977) and are now available in Python (2001),
Python Enhancement Proposals
PEP 255: Simple Generators
PEP 289: Generator Expressions
PEP 342: Coroutines via Enhanced Generators
C#, Ruby
Ruby is a pinkish-red-to-blood-red-colored gemstone, a variety of the mineral corundum ( aluminium oxide). Ruby is one of the most popular traditional jewelry gems and is very durable. Other varieties of gem-quality corundum are called sapph ...
, PHP, ECMAScript
ECMAScript (; ES) is a standard for scripting languages, including JavaScript, JScript, and ActionScript. It is best known as a JavaScript standard intended to ensure the interoperability of web pages across different web browsers. It is stan ...
(as of ES6/ES2015), and other languages. In CLU and C#, generators are called ''iterators'', and in Ruby, ''enumerators''.
Lisp
The final Common Lisp
Common Lisp (CL) is a dialect of the Lisp programming language, published in American National Standards Institute (ANSI) standard document ''ANSI INCITS 226-1994 (S2018)'' (formerly ''X3.226-1994 (R1999)''). The Common Lisp HyperSpec, a hyperli ...
standard does not natively provide generators, yet various library implementations exist, such a
SERIES
documented in CLtL2 o
pygen
CLU
A yield statement is used to implement iterators over user-defined data abstractions.
string_chars = iter (s: string) yields (char);
index: int := 1;
limit: int := string$size (s);
while index <= limit do
yield (string$fetch(s, index));
index := index + 1;
end;
end string_chars;
for c: char in string_chars(s) do
...
end;
Icon
Every expression (including loops) is a generator. The language has many generators built-in and even implements some of the logic semantics using the generator mechanism (logical disjunction
In logic, disjunction (also known as logical disjunction, logical or, logical addition, or inclusive disjunction) is a logical connective typically notated as \lor and read aloud as "or". For instance, the English language sentence "it is ...
or "OR" is done this way).
Printing squares from 0 to 20 can be achieved using a co-routine by writing:
local squares, j
squares := create (seq(0) ^ 2)
every j := , @squares do
if j <= 20 then
write(j)
else
break
However, most of the time custom generators are implemented with the "suspend" keyword which functions exactly like the "yield" keyword in CLU.
C
C does not have generator functions as a language construct, but, as they are a subset of coroutines, it is simple to implement them using any framework that implements stackful coroutines, such as libdill. On POSIX platforms, when the cost of context switching per iteration is not a concern, or full parallelism rather than merely concurrency is desired, a very simple generator function framework can be implemented using pthreads and pipes
Pipe(s), PIPE(S) or piping may refer to:
Objects
* Pipe (fluid conveyance), a hollow cylinder following certain dimension rules
** Piping, the use of pipes in industry
* Smoking pipe
** Tobacco pipe
* Half-pipe and quarter pipe, semi-circu ...
.
C++
It is possible to introduce generators into C++ using pre-processor macros. The resulting code might have aspects that are very different from native C++, but the generator syntax can be very uncluttered. The set of pre-processor macros defined in this source allow generators defined with the syntax as in the following example:
$generator(descent)
;
This can then be iterated using:
int main(int argc, char* argv[])
Moreover, C++11 allows foreach loops to be applied to any class that provides the begin
and end
functions. It's then possible to write generator-like classes by defining both the iterable methods (begin
and end
) and the iterator methods (operator!=
, operator++
and operator*
) in the same class. For example, it is possible to write the following program:
#include
int main()
A basic range implementation would look like that:
class range
;
Perl
Perl does not natively provide generators, but support is provided by th
Coro::Generator
module which uses th
Coro
co-routine framework. Example usage:
use strict;
use warnings;
# Enable generator and yield
use Coro::Generator;
# Array reference to iterate over
my $chars = A'...'Z'
# New generator which can be called like a coderef.
my $letters = generator ;
# Call the generator 15 times.
print $letters->(), "\n" for (0..15);
Raku
Example parallel to Icon uses Raku (formerly/aka Perl 6) Range class as one of several ways to achieve generators with the language.
Printing squares from 0 to 20 can be achieved by writing:
for (0 .. *).map(* ** 2) -> $i
However, most of the time custom generators are implemented with "gather" and "take" keywords in a lazy context.
Tcl
In Tcl 8.6, the generator mechanism is founded on named coroutine
Coroutines are computer program components that allow execution to be suspended and resumed, generalizing subroutines for cooperative multitasking. Coroutines are well-suited for implementing familiar program components such as cooperative task ...
s.
proc generator
# Use a simple 'for' loop to do the actual generation
set count enerator
# Pull values from the generator until it is exhausted
while 1
Haskell
In Haskell
Haskell () is a general-purpose, statically typed, purely functional programming language with type inference and lazy evaluation. Designed for teaching, research, and industrial applications, Haskell pioneered several programming language ...
, with its lazy evaluation
In programming language theory, lazy evaluation, or call-by-need, is an evaluation strategy which delays the evaluation of an Expression (computer science), expression until its value is needed (non-strict evaluation) and which avoids repeated eva ...
model, every datum created with a non-strict data constructor is generated on demand. For example,
countFrom :: Integer -> ntegercountFrom n = n : countFrom (n + 1)
from10to20 :: ntegerfrom10to20 = takeWhile (<= 20) $ countFrom 10
primes :: ntegerprimes = 2 : 3 : nextPrime 5
where
nextPrime n
, notDivisible n = n : nextPrime (n + 2)
, otherwise = nextPrime (n + 2)
notDivisible n =
all ((/= 0) . (rem n)) $ takeWhile ((<= n) . (^ 2)) $ tail primes
where (:)
is a non-strict list constructor, ''cons'', and $
is just a ''"called-with"'' operator, used for parenthesization. This uses the standard adaptor function,
takeWhile p [] = []
takeWhile p (x:xs) , p x = x : takeWhile p xs
, otherwise = []
which walks down the list and stops on the first element that doesn't satisfy the predicate. If the list has been walked before until that point, it is just a strict data structure, but if any part hadn't been walked through before, it will be generated on demand. List comprehensions can be freely used:
squaresUnder20 = takeWhile (<= 20) x <- countFrom 10squaresForNumbersUnder20 = x <- takeWhile (<= 20) $ countFrom 10
Racket
Racket provides several related facilities for generators. First, its for-loop forms work with ''sequences'', which are a kind of a producer:
(for ( (in-range 10 20)
(printf "i = ~s\n" i))
and these sequences are also first-class values:
(define 10-to-20 (in-range 10 20))
(for ( 10-to-20
(printf "i = ~s\n" i))
Some sequences are implemented imperatively (with private state variables) and some are implemented as (possibly infinite) lazy lists. Also, new struct definitions can have a property that specifies how they can be used as sequences.
But more directly, Racket comes with a generator library for a more traditional generator specification. For example,
#lang racket
(require racket/generator)
(define (ints-from from)
(generator ()
(for ( (in-naturals from) ; infinite sequence of integers from 0
(yield i))))
(define g (ints-from 10))
(list (g) (g) (g)) ; -> '(10 11 12)
Note that the Racket core implements powerful continuation features, providing general (re-entrant) continuations that are composable, and also delimited continuations. Using this, the generator library is implemented in Racket.
PHP
The community of PHP implemented generators in PHP 5.5. Details can be found in the origina
Request for Comments: Generators
Infinite Fibonacci sequence:
function fibonacci(): Generator
foreach (fibonacci() as $number)
Fibonacci sequence with limit:
function fibonacci(int $limit): Generator
foreach (fibonacci(10) as $number)
Any function which contains a yield statement is automatically a generator function.
Ruby
Ruby supports generators (starting from version 1.9) in the form of the built-in Enumerator class.
# Generator from an Enumerator object
chars = Enumerator.new( A', 'B', 'C', 'Z'
4.times
# Generator from a block
count = Enumerator.new do , yielder,
i = 0
loop
end
100.times
Java
Java has had a standard interface for implementing iterators since its early days, and since Java 5, the "foreach" construction makes it easy to loop over objects that provide the java.lang.Iterable
interface. (The Java collections framework and other collections frameworks, typically provide iterators for all collections.)
record Pair(int a, int b) ;
Iterable myIterable = Stream.iterate(new Pair(1, 1), p -> new Pair(p.b, p.a + p.b))
.limit(10)
.map(p -> p.a)::iterator;
myIterable.forEach(System.out::println);
Or get an Iterator from the Java 8 super-interface BaseStream of Stream interface.
record Pair(int a, int b) ;
// Save the iterator of a stream that generates fib sequence
Iterator myGenerator = Stream
// Generates Fib sequence
.iterate(new Pair(1, 1), p -> new Pair(p.b, p.a + p.b))
.map(p -> p.a).iterator();
// Print the first 5 elements
for (int i = 0; i < 5; i++)
System.out.println("done with first iteration");
// Print the next 5 elements
for (int i = 0; i < 5; i++)
Output:
1
1
2
3
5
done with first iteration
8
13
21
34
55
C#
An example C# 2.0 generator (the yield
is available since C# version 2.0):
Both of these examples utilize generics, but this is not required. yield keyword also helps in implementing custom stateful iterations over a collection as discussed in this discussion.
// Method that takes an iterable input (possibly an array)
// and returns all even numbers.
public static IEnumerable GetEven(IEnumerable numbers)
It is possible to use multiple yield return
statements and they are applied in sequence on each iteration:
public class CityCollection : IEnumerable
XL
In XL, iterators are the basis of 'for' loops:
import IO = XL.UI.CONSOLE
iterator IntegerIterator (var out Counter : integer; Low, High : integer) written Counter in Low..High is
Counter := Low
while Counter <= High loop
yield
Counter += 1
// Note that I needs not be declared, because declared 'var out' in the iterator
// An implicit declaration of I as an integer is therefore made here
for I in 1..5 loop
IO.WriteLn "I=", I
F#
F# provides generators via '' sequence expressions,'' since version 1.9.1. These can define a sequence (lazily evaluated, sequential access) via seq
, a list (eagerly evaluated, sequential access) via ... /code> or an array (eagerly evaluated, indexed access) via that contain code that generates values. For example,
seq
forms a sequence of squares of numbers from 0 to 14 by filtering out numbers from the range of numbers from 0 to 25.
Python
Generators were added to Python in version 2.2 in 2001. An example generator:
from typing import Iterator
def countfrom(n: int) -> Iterator nt
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.
import itertools
def primes() -> Iterator nt
"""Generate prime numbers indefinitely as needed."""
yield 2
n = 3
p = while True:
# If dividing n by all the numbers in p, up to and including sqrt(n),
# produces a non-zero remainder then n is prime.
if all(n % f > 0 for f in itertools.takewhile(lambda f: f * f <= n, p)):
yield n
p.append(n)
n += 2
In Python, a generator can be thought of as an iterator
In computer programming, an iterator is an object that progressively provides access to each item of a collection, in order.
A collection may provide multiple iterators via its interface that provide items in different orders, such as forwards ...
that contains a frozen stack frame. Whenever next()
is called on the iterator, 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.
PEP 380 (implemented in Python 3.3) adds the yield from
expression, allowing a generator to delegate part of its operations to another generator or iterable.PEP 380 -- Syntax for Delegating to a Subgenerator
/ref>
Generator expressions
Python has a syntax modeled on that of list comprehensions, called a generator expression that aids in the creation of generators.
The following extends the first example above by using a generator expression to compute squares from the countfrom
generator function:
squares = (n * n for n in countfrom(2))
for j in squares:
if j <= 20:
print(j)
else:
break
ECMAScript
ECMAScript 6 (a.k.a. Harmony) introduced generator functions.
An infinite Fibonacci sequence can be written using a function generator:
function* fibonacci(limit)
// bounded by upper limit 10
for (const n of fibonacci(10))
// generator without an upper bound limit
for (const n of fibonacci())
// manually iterating
let fibGen = fibonacci();
console.log(fibGen.next().value); // 1
console.log(fibGen.next().value); // 1
console.log(fibGen.next().value); // 2
console.log(fibGen.next().value); // 3
console.log(fibGen.next().value); // 5
console.log(fibGen.next().value); // 8
// picks up from where you stopped
for (const n of fibGen)
R
The iterators package can be used for this purpose.
library(iterators)
# Example ------------------
abc <- iter(c('a','b','c'))
nextElem(abc)
Smalltalk
Example in Pharo Smalltalk:
The Golden ratio
In mathematics, two quantities are in the golden ratio if their ratio is the same as the ratio of their summation, sum to the larger of the two quantities. Expressed algebraically, for quantities and with , is in a golden ratio to if
\fr ...
generator below returns to each invocation 'goldenRatio next' a better approximation to the Golden Ratio.
goldenRatio := Generator on: , x y z r ,
x := 0.
y := 1.
repeat
">
z := x + y.
r := (z / y) asFloat.
x := y.
y := z.
g yield: r
repeat
goldenRatio next.
The expression below returns the next 10 approximations.
Character cr join: ((1 to: 10) collect: :dummy , ratio next .
See more i
A hidden gem in Pharo: Generator
See also
* List comprehension for another construct that generates a sequence of values
* Iterator
In computer programming, an iterator is an object that progressively provides access to each item of a collection, in order.
A collection may provide multiple iterators via its interface that provide items in different orders, such as forwards ...
for the concept of producing a list one element at a time
* Iteratee for an alternative
* Lazy evaluation
In programming language theory, lazy evaluation, or call-by-need, is an evaluation strategy which delays the evaluation of an Expression (computer science), expression until its value is needed (non-strict evaluation) and which avoids repeated eva ...
for producing values when needed
* Corecursion
In computer science, corecursion is a type of operation that is Dual (category theory), dual to recursion (computer science), recursion. Whereas recursion works analysis, analytically, starting on data further from a base case and breaking it dow ...
for potentially infinite data by recursion instead of ''yield''
* Coroutine
Coroutines are computer program components that allow execution to be suspended and resumed, generalizing subroutines for cooperative multitasking. Coroutines are well-suited for implementing familiar program components such as cooperative task ...
for even more generalization from subroutine
* Continuation
In computer science, a continuation is an abstract representation of the control state of a computer program. A continuation implements ( reifies) the program control state, i.e. the continuation is a data structure that represents the computat ...
for generalization of control flow
Notes
References
* 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
{{Authority control
Programming constructs
Articles with example Python (programming language) code
Articles with example Haskell code
Articles with example Ruby code
Articles with example C Sharp code
Articles with example Java code
Articles with example Perl code
Articles with example Tcl code
Articles with example Racket code
Iteration in programming
Articles with example R code> ... , /code> that contain code that generates values. For example,
seq
forms a sequence of squares of numbers from 0 to 14 by filtering out numbers from the range of numbers from 0 to 25.
Python
Generators were added to Python in version 2.2 in 2001. An example generator:
from typing import Iterator
def countfrom(n: int) -> Iterator nt
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.
import itertools
def primes() -> Iterator nt
"""Generate prime numbers indefinitely as needed."""
yield 2
n = 3
p = while True:
# If dividing n by all the numbers in p, up to and including sqrt(n),
# produces a non-zero remainder then n is prime.
if all(n % f > 0 for f in itertools.takewhile(lambda f: f * f <= n, p)):
yield n
p.append(n)
n += 2
In Python, a generator can be thought of as an iterator
In computer programming, an iterator is an object that progressively provides access to each item of a collection, in order.
A collection may provide multiple iterators via its interface that provide items in different orders, such as forwards ...
that contains a frozen stack frame. Whenever next()
is called on the iterator, 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.
PEP 380 (implemented in Python 3.3) adds the yield from
expression, allowing a generator to delegate part of its operations to another generator or iterable.PEP 380 -- Syntax for Delegating to a Subgenerator
/ref>
Generator expressions
Python has a syntax modeled on that of list comprehensions, called a generator expression that aids in the creation of generators.
The following extends the first example above by using a generator expression to compute squares from the countfrom
generator function:
squares = (n * n for n in countfrom(2))
for j in squares:
if j <= 20:
print(j)
else:
break
ECMAScript
ECMAScript 6 (a.k.a. Harmony) introduced generator functions.
An infinite Fibonacci sequence can be written using a function generator:
function* fibonacci(limit)
// bounded by upper limit 10
for (const n of fibonacci(10))
// generator without an upper bound limit
for (const n of fibonacci())
// manually iterating
let fibGen = fibonacci();
console.log(fibGen.next().value); // 1
console.log(fibGen.next().value); // 1
console.log(fibGen.next().value); // 2
console.log(fibGen.next().value); // 3
console.log(fibGen.next().value); // 5
console.log(fibGen.next().value); // 8
// picks up from where you stopped
for (const n of fibGen)
R
The iterators package can be used for this purpose.
library(iterators)
# Example ------------------
abc <- iter(c('a','b','c'))
nextElem(abc)
Smalltalk
Example in Pharo Smalltalk:
The Golden ratio
In mathematics, two quantities are in the golden ratio if their ratio is the same as the ratio of their summation, sum to the larger of the two quantities. Expressed algebraically, for quantities and with , is in a golden ratio to if
\fr ...
generator below returns to each invocation 'goldenRatio next' a better approximation to the Golden Ratio.
goldenRatio := Generator on: , x y z r ,
x := 0.
y := 1.
repeat
">
z := x + y.
r := (z / y) asFloat.
x := y.
y := z.
g yield: r
repeat
goldenRatio next.
The expression below returns the next 10 approximations.
Character cr join: ((1 to: 10) collect: :dummy , ratio next .
See more i
A hidden gem in Pharo: Generator
See also
* List comprehension for another construct that generates a sequence of values
* Iterator
In computer programming, an iterator is an object that progressively provides access to each item of a collection, in order.
A collection may provide multiple iterators via its interface that provide items in different orders, such as forwards ...
for the concept of producing a list one element at a time
* Iteratee for an alternative
* Lazy evaluation
In programming language theory, lazy evaluation, or call-by-need, is an evaluation strategy which delays the evaluation of an Expression (computer science), expression until its value is needed (non-strict evaluation) and which avoids repeated eva ...
for producing values when needed
* Corecursion
In computer science, corecursion is a type of operation that is Dual (category theory), dual to recursion (computer science), recursion. Whereas recursion works analysis, analytically, starting on data further from a base case and breaking it dow ...
for potentially infinite data by recursion instead of ''yield''
* Coroutine
Coroutines are computer program components that allow execution to be suspended and resumed, generalizing subroutines for cooperative multitasking. Coroutines are well-suited for implementing familiar program components such as cooperative task ...
for even more generalization from subroutine
* Continuation
In computer science, a continuation is an abstract representation of the control state of a computer program. A continuation implements ( reifies) the program control state, i.e. the continuation is a data structure that represents the computat ...
for generalization of control flow
Notes
References
* 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
{{Authority control
Programming constructs
Articles with example Python (programming language) code
Articles with example Haskell code
Articles with example Ruby code
Articles with example C Sharp code
Articles with example Java code
Articles with example Perl code
Articles with example Tcl code
Articles with example Racket code
Iteration in programming
Articles with example R code