.. include:: ../../global.rst .. _`pair type`: Pair Type ========= Pairs are the primary compound type. A pair is a value with references to two other values called the *head* and *tail*. A pair is printed as :samp:`({head} & {tail})`. If the tail references another pair then you can envisage a chain forming, more commonly called a *list*. Lists ----- Lists are an emergent property of chained pairs and are commonly written and printed without superfluous chaining punctuation so: :samp:`({e1} & ({e2} & ({e3} & #n)))` is the more convenient: :samp:`({e1} {e2} {e3})` If the tail of the last element of the list is not ``#n`` then the list is an *improper* list and is printed as: :samp:`({e1} {e2} & {e3})` This form is commonly used in the *formals* of a function definition to denote a varargs parameter, that is, bundle any remaining arguments up into a list. When the :ref:`evaluator ` sees a list it interprets it as a function call. However, if you simply want to create a list variable you need to *quote* the list to prevent the evaluator processing it as a function call: .. code-block:: idio my-list := '(1 2 3) Superficially, with "only the *head* to play with", lists seem relatively limited. However, the structure pointed to by the head can be arbitrarily complex. Association Lists ^^^^^^^^^^^^^^^^^ One simple form of that complexity is if the head is itself a list. This is called an association list where there are a number of functions that will walk over the (top-level) list looking for a key matching the first element of one of the sub-lists which it will return: .. code-block:: idio al := '((#\a "apple" 'fruit) (#\b "banana" 'fruit) (#\c "carrot" 'vegetable)) assq #\b al ; '(#\b "banana" 'fruit) Pair Predicates --------------- .. _`pair?`: .. idio:function:: pair? o test if `o` is a pair :param o: object to test :return: ``#t`` if `o` is a pair, ``#f`` otherwise .. _`list?`: .. idio:function:: list? v Is `v` a list? :param v: value to test :return: any :rtype: boolean Pair Constructors ----------------- .. _`pair`: .. idio:function:: pair h t create a `pair` from `h` and `t` .. _`list`: .. idio:function:: list args return `args` as a list :param args: arguments to convert :return: list of `args` :rtype: list .. _`string->list`: .. idio:function:: string->list s return a list of the Unicode code points in `s` :param s: string :type s: string :return: list of Unicode code points :rtype: list .. _`array->list`: .. idio:function:: array->list a convert `a` to a list :param a: the array :type a: array :return: list :rtype: list Pair Attributes --------------- .. _`ph`: .. idio:function:: ph p return the head of pair `p` :param p: pair to query :type p: pair :return: head of `p` .. _`pt`: .. idio:function:: pt p return the tail of pair `p` :param p: pair to query :type p: pair :return: tail of `p` .. _`set-ph!`: .. idio:function:: set-ph! p v set the head of pair `p` to `v` :param p: pair to modify :type p: pair :param v: value :type v: any :return: ``#`` .. _`set-pt!`: .. idio:function:: set-pt! p v set the tail of pair `p` to `v` :param p: pair to modify :type p: pair :param v: value :type v: any :return: ``#`` .. _`list-ref`: .. idio:function:: list-ref x n return the element of `x` at position `n` :param x: list to examine :type x: list :param n: index of element to access :type n: integer .. _`list-tail`: .. idio:function:: list-tail list pos Return the list after `pos` pairs of `list` :param list: list to be examined :type list: list :param pos: pos :type pos: fixnum :return: list after `pos` pairs of `list` :rtype: list .. _`last-pair`: .. idio:function:: last-pair list Return the last pair of `list` :param list: list to be examined :type list: list :return: last pair of `list` :rtype: pair .. _`nth`: .. idio:function:: nth l n [default] return the nth (`n`) element from list `l` :param l: list :type orig: list :param n: nth element :type n: integer :param default: value to return if not found, defaults to ``#n`` :type default: value, optional :return: the element or `default` :rtype: any ``nth`` uses 0-based indexing. `n` can be negative to access the n\ :sup:`th` from the end of the list with ``-1`` being the last element. .. _`set-nth!`: .. idio:function:: set-nth! l n val set the nth (`n`) element in list `l` :param l: list :type orig: list :param n: nth element :type n: integer :param val: value to assign :type val: any :return: ``#`` ``set-nth!`` uses 0-based indexing. `n` can be negative to set the n\ :sup:`th` from the end of the list with ``-1`` being the last element. Pair Accessors -------------- Following are a number of variations on a theme of accessing elements in a chain of pairs. The order of ``h``\ s and ``t``\ s in the function names reflects the left-to-right ordering of the function calls. For some :samp:`p{X}{Y} x` you can read as :samp:`the p{X} of the p{Y} of x`. .. _`phh`: .. idio:function:: phh p return :samp:`(ph (ph {p}))` :param p: pair to query :type p: pair :return: head of the head of `p` .. _`phhh`: .. idio:function:: phhh p return :samp:`(ph (ph (ph {p})))` :param p: pair to query :type p: pair :return: head of the head of the head of `p` .. _`phhhh`: .. idio:function:: phhhh x .. _`phhht`: .. idio:function:: phhht x .. _`phht`: .. idio:function:: phht x .. _`phhth`: .. idio:function:: phhth x .. _`phhtt`: .. idio:function:: phhtt x .. _`pht`: .. idio:function:: pht p return :samp:`(ph (pt {p}))` :param p: pair to query :type p: pair :return: head of the tail of `p` .. _`phth`: .. idio:function:: phth p return :samp:`(ph (pt (ph {p})))` :param p: pair to query :type p: pair :return: head of the tail of the head of `p` .. _`phthh`: .. idio:function:: phthh x .. _`phtht`: .. idio:function:: phtht x .. _`phtt`: .. idio:function:: phtt p return :samp:`(ph (pt (pt {p})))` :param p: pair to query :type p: pair :return: head of the tail of the tail of `p` .. _`phtth`: .. idio:function:: phtth p return :samp:`(ph (pt (pt (ph {p}))))` :param p: pair to query :type p: pair :return: head of the tail of the tail of the head of `p` .. _`phttt`: .. idio:function:: phttt x .. _`pth`: .. idio:function:: pth p return :samp:`(pt (ph {p}))` :param p: pair to query :type p: pair :return: tail of the head of `p` .. _`pthh`: .. idio:function:: pthh x .. _`pthhh`: .. idio:function:: pthhh x .. _`pthht`: .. idio:function:: pthht x .. _`ptht`: .. idio:function:: ptht x .. _`pthth`: .. idio:function:: pthth x .. _`pthtt`: .. idio:function:: pthtt x .. _`ptt`: .. idio:function:: ptt p return :samp:`(pt (pt {p}))` :param p: pair to query :type p: pair :return: tail of the tail of `p` .. _`ptth`: .. idio:function:: ptth p return :samp:`(pt (pt (ph {p})))` :param p: pair to query :type p: pair :return: tail of the tail of the head of `p` .. _`ptthh`: .. idio:function:: ptthh x .. _`pttht`: .. idio:function:: pttht x .. _`pttt`: .. idio:function:: pttt p return :samp:`(pt (pt (pt {p})))` :param p: pair to query :type p: pair :return: tail of the tail of the tail of `p` .. _`pttth`: .. idio:function:: pttth x .. _`ptttt`: .. idio:function:: ptttt x Pair Functions -------------- .. _`reverse`: .. idio:function:: reverse l reverse the list `l` :param l: list to reverse :type l: list :return: reversed list .. _`reverse!`: .. idio:function:: reverse! l reverse the list `l` destructively :param l: list to reverse :type l: list :return: reversed list Calling ``reverse!`` on a list that others are referencing may have undesired effects: .. code-block:: idio-console Idio> lst := '(1 2 3) (1 2 3) Idio> reverse! lst (3 2 1) Idio> lst (1) .. _`length`: .. idio:function:: length l return the number of elements in list `l` :param l: list to count :type l: list :return: number of elements in `l` :rtype: integer .. _`append`: .. idio:function:: append [a] append the lists of `a` :param a: list of lists :return: combined list :rtype: list .. _`append!`: .. idio:function:: append! lists Destructively append `lists` :param lists: lists to be appended :type lists: lists :return: combined lists :rtype: list .. _`memq`: .. idio:function:: memq k l return the remainder of the list `l` from the first incidence of an element :ref:`eq? ` `k` or ``#f`` if `k` is not in `l` :param k: object to search for :type k: any :param l: list to search in :type l: list :return: a list starting from `k`, ``#f`` if `k` is not in `l` .. _`memv`: .. idio:function:: memv k l return the remainder of the list `l` from the first incidence of an element :ref:`eqv? ` `k` or ``#f`` if `k` is not in `l` :param k: object to search for :type k: any :param l: list to search in :type l: list :return: a list starting from `k`, ``#f`` if `k` is not in `l` .. _`member`: .. idio:function:: member k l return the remainder of the list `l` from the first incidence of an element :ref:`equal? ` `k` or ``#f`` if `k` is not in `l` :param k: object to search for :type k: any :param l: list to search in :type l: list :return: a list starting from `k`, ``#f`` if `k` is not in `l` .. _`assq`: .. idio:function:: assq k l return the first entry of association list `l` with a key :ref:`eq? ` `k` or ``#f`` if `k` is not a key in `l` :param k: object to search for :type k: any :param l: association list to search in :type l: list :return: the list (`k` & value), ``#f`` if `k` is not a key in `l` .. _`assv`: .. idio:function:: assv k l return the first entry of association list `l` with a key :ref:`eqv? ` `k` or ``#f`` if `k` is not a key in `l` :param k: object to search for :type k: any :param l: association list to search in :type l: list :return: the list (`k` & value), ``#f`` if `k` is not a key in `l` .. _`assoc`: .. idio:function:: assoc k l return the first entry of association list `l` with a key :ref:`equal? ` `k` or ``#f`` if `k` is not a key in `l` :param k: object to search for :type k: any :param l: association list to search in :type l: list :return: the list (`k` & value), ``#f`` if `k` is not a key in `l` .. include:: ../../commit.rst