hy/docs/contrib/sequences.rst
2016-11-08 21:23:49 +02:00

78 lines
2.1 KiB
ReStructuredText

==============
Lazy sequences
==============
.. versionadded:: 0.12.0
Sequences module contains few macros for declaring sequences that are evaluated
only as much as the client code requests elements. Compared to generators they
allow accessing same element multiple times. Since they cache calculated
values, they aren't suited for infinite sequences. However, the implementation
allows recursive definition of sequences, without resulting recursive
computation.
To use these macros you need to require them and import other types like:
.. code-block:: hy
(require [hy.contrib.sequences [defseq seq]])
(import [hy.contrib.sequences [Sequence end-sequence]])
Simplest sequence can be defined as: ``(seq [n] n)``. This defines a sequence
that starts as: ``[0 1 2 3 ...]`` and continues forever. In order to define
a finite sequence, ``end-sequence`` needs to be called to signal end of
the sequence:
.. code-block:: hy
(seq [n]
(cond [(< n 5) n]
[true (end-sequence)]))
This creates following sequence: ``[0 1 2 3 4]``. For such a sequence ``len``
returns amount of items in sequence and negative indexing is suported. Because
both of thse require evaluating whole sequence, calling such a function would
take forever (or at least until available memory has been exhausted).
Sequence can be defined recursively. Canonical example of fibonacci numbers
is defined as:
.. code-block:: hy
(defseq fibonacci [n]
(cond [(= n 0) 0]
[(= n 1) 1]
[true (+ (get fibonacci (- n 1))
(get fibonacci (- n 2)))]))
This results sequence of ``[0 1 1 2 3 5 8 13 21 34 ...]``.
.. _seq:
seq
===
Usage: ``(seq [n] (* n n)``
Creates a sequence defined in terms of ``n``.
.. _defseq:
defseq
======
Usage: ``(defseq numbers [n] n)``
Creates a sequence defined in terms of ``n`` and assigns it to a given name.
.. _end-sequence:
end-sequence
============
Usage: ``(seq [n] (if (< n 5) n (end-sequence)))``
Signals end of a sequence when iterator reaches certain point of sequence.
Internally this is done by raising ``IndexError``, catching that in iterator
and raising ``StopIteration``.