2016-11-08 05:28:12 +01:00
|
|
|
==============
|
|
|
|
Lazy sequences
|
|
|
|
==============
|
|
|
|
|
|
|
|
.. versionadded:: 0.12.0
|
|
|
|
|
2016-12-08 01:12:57 +01:00
|
|
|
The sequences module contains a few macros for declaring sequences that are
|
|
|
|
evaluated only as much as the client code requires. Unlike generators, they
|
|
|
|
allow accessing the same element multiple times. They cache calculated values,
|
|
|
|
and the implementation allows for recursive definition of sequences without
|
|
|
|
resulting in recursive computation.
|
2016-11-08 05:28:12 +01:00
|
|
|
|
2016-12-08 01:12:57 +01:00
|
|
|
To use these macros, you need to require them and import some other names like
|
|
|
|
so:
|
2016-11-08 05:28:12 +01:00
|
|
|
|
|
|
|
.. code-block:: hy
|
|
|
|
|
|
|
|
(require [hy.contrib.sequences [defseq seq]])
|
|
|
|
(import [hy.contrib.sequences [Sequence end-sequence]])
|
|
|
|
|
2016-12-08 01:12:57 +01:00
|
|
|
The 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, you need to call ``end-sequence`` to signal the end of the
|
|
|
|
sequence:
|
2016-11-08 05:28:12 +01:00
|
|
|
|
|
|
|
.. code-block:: hy
|
|
|
|
|
|
|
|
(seq [n]
|
2016-11-09 07:52:18 +01:00
|
|
|
"sequence of 5 integers"
|
2016-11-08 05:28:12 +01:00
|
|
|
(cond [(< n 5) n]
|
2016-12-08 01:12:57 +01:00
|
|
|
[True (end-sequence)]))
|
2016-11-08 05:28:12 +01:00
|
|
|
|
2016-12-08 01:12:57 +01:00
|
|
|
This creates the following sequence: ``[0 1 2 3 4]``. For such a sequence,
|
|
|
|
``len`` returns the amount of items in the sequence and negative indexing is
|
|
|
|
supported. Because both of these require evaluating the whole sequence, calling
|
|
|
|
one on an infinite sequence would take forever (or at least until available
|
|
|
|
memory has been exhausted).
|
2016-11-08 05:28:12 +01:00
|
|
|
|
2016-12-08 01:12:57 +01:00
|
|
|
Sequences can be defined recursively. For example, the Fibonacci sequence could
|
|
|
|
be defined as:
|
2016-11-08 05:28:12 +01:00
|
|
|
|
|
|
|
.. code-block:: hy
|
|
|
|
|
|
|
|
(defseq fibonacci [n]
|
2016-11-09 07:52:18 +01:00
|
|
|
"infinite sequence of fibonacci numbers"
|
2016-11-08 05:28:12 +01:00
|
|
|
(cond [(= n 0) 0]
|
|
|
|
[(= n 1) 1]
|
2016-12-08 01:12:57 +01:00
|
|
|
[True (+ (get fibonacci (- n 1))
|
2016-11-08 05:28:12 +01:00
|
|
|
(get fibonacci (- n 2)))]))
|
|
|
|
|
2016-12-08 01:12:57 +01:00
|
|
|
This results in the sequence ``[0 1 1 2 3 5 8 13 21 34 ...]``.
|
2016-11-08 05:28:12 +01:00
|
|
|
|
|
|
|
.. _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)))``
|
|
|
|
|
2016-12-08 01:12:57 +01:00
|
|
|
Signals the end of a sequence when an iterator reaches the given
|
|
|
|
point of the sequence. Internally, this is done by raising
|
|
|
|
``IndexError``, catching that in the iterator, and raising
|
|
|
|
``StopIteration``.
|