.. _type-list:
Lists
=====
A list is a sequence of values of the same type. Lists are
constructed via the ``list`` constructor function, e.g., ``list[1, 2,
3]`` creates a list of three integers. An empty list is created via
``list[]`` or ``Nil``.
The time to access a value via ``nth`` is proportional to the length
of the list. The first value of a list can be accessed in constant
time, using the ``head`` function.
The ``map``, ``fold`` and ``filter`` second-order functions described
in this section implement common functional programming patterns. To
execute some statements for each element in a list, use a ``foreach``
loop (see :ref:`foreach-loop`).
Datatypes and constructors
--------------------------
A list is defined either as the empty list (``Nil``) or as a value
``a`` followed by another list ``l`` (``Cons(a, l)``)::
data List = Nil | Cons(A head, List tail);
Literal lists of arbitrary length can be written using a special
function ``list``. In the following example, ``l1`` and ``l2``
contain the same elements::
List l1 = list[1, 2, 3];
List l2 = Cons(1, Cons(2, Cons(3, Nil)));
Functions
---------
head
^^^^
Returns the head of a list.
::
head(list[1, 2, 3])
// => 1
tail
^^^^
Returns the tail (rest) of a list.
::
tail(list[1, 2, 3])
// => list[2, 3]
length
^^^^^^
Returns the length of a list. The length of ``Nil`` is 0.
::
length(list[1, 2, 3])
// => 3
isEmpty
^^^^^^^
Checks if a list is empty. Returns ``True`` for ``Nil``, ``False``
otherwise.
::
isEmpty(list[1, 2, 3])
// => False
isEmpty(list[])
// => True
nth
^^^
Returns the ``n``-th element of a list. Returns the head of ``l`` for
``n``=0, returns the last element of ``l`` when ``n`` is
``length(l)-1``.
It is an error if ``n`` is equal to or larger than ``length(l)``.
::
nth(list[1, 2, 3], 2)
// => 3
without
^^^^^^^
Returns a fresh list where all occurrences of ``a`` have been removed.
::
without(list[1, 2, 3, 3, 5], 3)
// => list[1, 2, 5]
concatenate
^^^^^^^^^^^
Returns a list containing all elements of list ``list1`` followed by
all elements of list ``list2``.
::
concatenate(list[1, 2, 3], list[4, 5])
// => list[1, 2, 3, 4, 5]
appendright
^^^^^^^^^^^
Returns a list containing all elements of list ``l`` followed by the
element ``p`` in the last position.
::
appendright(list[1, 2], 3)
// => list[1, 2, 3]
reverse
^^^^^^^
Returns a list containing all elements of ``l`` in reverse order.
::
reverse(list[1, 2, 3])
// => list[3, 2, 1]
copy
^^^^
Returns a list of length ``n`` containing ``p`` n times.
::
copy(-1, 4)
// => list[-1, -1, -1, -1]
map
^^^
Applies a function to each element of a list, returning a list of
results in the same order. The function ``fn`` must take an argument
of type ``A`` and return a value of type ``B``.
::
map((Int x) => x + 1)(list[1, 2, 3])
// => list[2, 3, 4]
filter
^^^^^^
Returns a list containing only the elements in the given list for
which the given predicate returns ``True``. The function
``predicate`` must take an argument of type ``T`` and return a Boolean
value.
::
filter((Int x) => x < 4)(list[1, 2, 3, 4, 5])
// => list[1, 2, 3]
foldl
^^^^^
Accumulates a value starting with ``init`` and applying ``accumulate``
from left to right to current accumulator value and each element. The
function ``accumulate`` must take two arguments: the first of type
``A`` (the type of the list) and the second of type ``B`` (the
accumulator and result type), and return a value of type ``B``.
::
foldl((Int x, String res) => res + toString(x))(list[1, 2, 3], "")
// => "123"
foldr
^^^^^
Accumulates a value starting with ``init`` and applying ``accumulate``
from right to left to each element and current accumulator value. The
function ``accumulate`` must take two arguments: the first of type
``A`` (the type of the list) and the second of type ``B`` (the
accumulator and result type), and return a value of type ``B``.
::
foldl((Int x, String res) => res + toString(x))(list[1, 2, 3], "")
// => "321"
range
^^^^^
Returns a list of integers ranging from the first to the second
argument, inclusive. If ``lower`` is equal to ``upper``, returns a
list of one element; if ``lower`` is larger than ``upper``, returns an
empty list.
::
range(2, 5)
// => list[2, 3, 4, 5]