series (version 0.2+) | index /home/beni/hacks/python/series.py |
Lazy series abstraction tightly integrated with iterators.
This module exposes the duality between linked lists and iterators:
- Simple linked lists have the drawback that their tail must be known and
finite. This can be fixed by overloading head/tail access and making it
lazy; the resulting facility is popular in functional programming languages.
This is implemented by the `Series` classes.
- Iterators have the drawback of being stateful (advancing them is
destructive) but there is no way to capture the "remaining future" of an
iterator at some moment. This can be fixed by making an iterator explicitly
point to a series and allow separate iterators to be forked from it. This
is implemented by the `SeriesIter` class.
Another useful thing about linked lists is that you can non-destructively cons
items in front of them. This is implemented by the `Series` constructor (which is
also used to represent the part of series that has already been computed) and
is also accessible through the `SeriesIter.unyield()` method.
A ``__series__()`` protocol is defined, paralleling ``__iter__()``. Object
can implement it to provide special implementaion of series over them (but
normally you would simply implement ``__iter__()`` and `Series` will know to
wrap it). On series objects this method returns self.
A convenince subscripting interface is provided for series.
:See also:
- The `Streams chapter of SICP`__ shows how streams with a lazy tail can be
a very powerful abstraction.
__ http://mitpress.mit.edu/sicp/full-text/book/book-Z-H-24.html#%_sec_3.5
- `SRFI 40: A Library of Streams`__ specifies streams whose head is lazy
too, which is more elegant and predictable. It's also a better parallel
for iterators. This is the flavour implemented by this module.
__ http://srfi.schemers.org/srfi-40/srfi-40.html
- `Appendix A of Common Lisp the Language: Series`__ specifies a very
extensive set of operations on lazy sequences. It does *not* implement
them as linked lists and does not make it easy to take references into
the middle of a series; instead it statically optimizes code involving
series into very effecient loops. `Appendix B: Generators and
Gatherers`__, describes a facility very similar to Python's iterators and
their inverse (send multiple values to object, get summary value in the
end). It implements them as a thin layer upon the Series facility, which
is similar to what this module does with `SeriesIter`.
__ http://www.supelec.fr/docs/cltl/clm/node347.html
__ http://www.supelec.fr/docs/cltl/clm/node362.html
The name "streams" seems to be more widely known among functional
programmers and the "series" facility is somewhat different from what we
build here. Nevertheless, I chose "series" for this module since it has no
other accepted meanings while "streams" is overloaded with associations,
especially I/O...
Classes | ||||||||||||||||||
|
Data | ||
__author__ = 'Beni Cherniavsky <cben@users.sf.net>' __license__ = 'LGPL <http://www.gnu.org/copyleft/lesser.html>' __url__ = 'http://cben-hacks.sf.net/python/' __version__ = '0.2+' |
Author | ||
Beni Cherniavsky <cben@users.sf.net> |