% This LaTeX document was generated using the LaTeX backend of PlDoc,
% The SWI-Prolog documentation system



\subsection{Introduction}

\label{sec:assoc-introduction}

An \textit{association list} as implemented by this library is a collection
of unique \textit{keys} that are associated to \textit{values}. Keys must be ground,
values need not be.

An association list can be used to \textit{fetch} elements via their keys and
to \textit{enumerate} its elements in ascending order of their keys.

This library uses \textbf{AVL trees} to implement association lists. This means that

\begin{shortlist}
    \item inserting a key
    \item changing an association
    \item fetching a single element
\end{shortlist}

are all \textit{O(\const{log(N)})} \textit{worst-case} (and expected) time operations, where
\textit{N} denotes the number of elements in the association list.

The logarithmic overhead is often acceptable in practice. Notable
advantages of association lists over several other methods are:

\begin{itemize}
    \item \verb$library(assoc)$ is written entirely in Prolog, making it portable to
other systems
    \item the interface predicates fit the declarative nature of Prolog, avoiding
destructive updates to terms
    \item AVL trees scale very predictably and can be used to represent sparse arrays
efficiently.
\end{itemize}

\subsection{Creating association lists}

\label{sec:assoc-creation}

An assocation list is \textit{created} with one of the following predicates:

\begin{description}
    \predicate[semidet]{empty_assoc}{1}{?Assoc}
Is true if \arg{Assoc} is the empty association list.

    \predicate[det]{list_to_assoc}{2}{+Pairs, -Assoc}
Create an association from a list \arg{Pairs} of Key-Value pairs. List
must not contain duplicate keys.

\begin{tags}
    \tag{Errors}
\verb$domain_error(unique_key_pairs, List)$ if List contains duplicate keys
\end{tags}

    \predicate[det]{ord_list_to_assoc}{2}{+Pairs, -Assoc}
\arg{Assoc} is created from an ordered list \arg{Pairs} of Key-Value
pairs. The pairs must occur in strictly ascending order of
their keys.

\begin{tags}
    \tag{Errors}
\verb$domain_error(key_ordered_pairs, List)$ if pairs are not ordered.
\end{tags}
\end{description}

\subsection{Querying association lists}

\label{sec:assoc-querying}

An association list can be \textit{queried} with:

\begin{description}
    \predicate[semidet]{get_assoc}{3}{+Key, +Assoc, -Value}
True if \arg{Key}-\arg{Value} is an association in \arg{Assoc}.

\begin{tags}
    \tag{Errors}
\verb$type_error(assoc, Assoc)$ if \arg{Assoc} is not an association list.
\end{tags}

    \predicate[semidet]{get_assoc}{5}{+Key, +Assoc0, ?Val0, ?Assoc, ?Val}
True if \arg{Key}-\arg{Val0} is in \arg{Assoc0} and \arg{Key}-\arg{Val} is in \arg{Assoc}.

    \predicate[semidet]{max_assoc}{3}{+Assoc, -Key, -Value}
True if \arg{Key}-\arg{Value} is in \arg{Assoc} and \arg{Key} is the largest key.

    \predicate[semidet]{min_assoc}{3}{+Assoc, -Key, -Value}
True if \arg{Key}-\arg{Value} is in assoc and \arg{Key} is the smallest key.

    \predicate[nondet]{gen_assoc}{3}{?Key, +Assoc, ?Value}
True if \arg{Key}-\arg{Value} is an association in \arg{Assoc}. Enumerates keys in
ascending order on backtracking.

\begin{tags}
    \tag{See also}
\predref{get_assoc}{3}.
\end{tags}
\end{description}

\subsection{Modifying association lists}

\label{sec:assoc-modifications}

Elements of an association list can be changed and inserted with:

\begin{description}
    \predicate[det]{put_assoc}{4}{+Key, +Assoc0, +Value, -Assoc}
\arg{Assoc} is \arg{Assoc0}, except that \arg{Key} is associated with
\arg{Value}. This can be used to insert and change associations.

    \predicate[semidet]{del_assoc}{4}{+Key, +Assoc0, ?Value, -Assoc}
True if \arg{Key}-\arg{Value} is in \arg{Assoc0}. \arg{Assoc} is \arg{Assoc0} with
\arg{Key}-\arg{Value} removed.

    \predicate[semidet]{del_min_assoc}{4}{+Assoc0, ?Key, ?Val, -Assoc}
True if \arg{Key}-Value is in \arg{Assoc0} and \arg{Key} is the smallest key.
\arg{Assoc} is \arg{Assoc0} with \arg{Key}-Value removed. Warning: This will
succeed with \textit{no} bindings for \arg{Key} or \arg{Val} if \arg{Assoc0} is empty.

    \predicate[semidet]{del_max_assoc}{4}{+Assoc0, ?Key, ?Val, -Assoc}
True if \arg{Key}-Value is in \arg{Assoc0} and \arg{Key} is the greatest key.
\arg{Assoc} is \arg{Assoc0} with \arg{Key}-Value removed. Warning: This will
succeed with \textit{no} bindings for \arg{Key} or \arg{Val} if \arg{Assoc0} is empty.
\end{description}

\subsection{Conversion predicates}

\label{sec:assoc-conversion}

Conversion of (parts of) an association list to \textit{lists} is possible
with:

\begin{description}
    \predicate[det]{assoc_to_list}{2}{+Assoc, -Pairs}
Translate \arg{Assoc} to a list \arg{Pairs} of Key-Value pairs. The keys
in \arg{Pairs} are sorted in ascending order.

    \predicate[det]{assoc_to_keys}{2}{+Assoc, -Keys}
True if \arg{Keys} is the list of keys in \arg{Assoc}. The keys are sorted
in ascending order.

    \predicate[det]{assoc_to_values}{2}{+Assoc, -Values}
True if \arg{Values} is the list of values in \arg{Assoc}. \arg{Values} are
ordered in ascending order of the key to which they were
associated. \arg{Values} may contain duplicates.
\end{description}

\subsection{Reasoning about association lists and their elements}

\label{sec:assoc-reasoning}

Further inspection predicates of an association list and its elements
are:

\begin{description}
    \predicate[semidet]{is_assoc}{1}{+Assoc}
True if \arg{Assoc} is an association list. This predicate checks
that the structure is valid, elements are in order, and tree
is balanced to the extent guaranteed by AVL trees. I.e.,
branches of each subtree differ in depth by at most 1.

    \predicate[semidet]{map_assoc}{2}{:Pred, +Assoc}
True if \arg{Pred}(Value) is true for all values in \arg{Assoc}.

    \predicate[semidet]{map_assoc}{3}{:Pred, +Assoc0, ?Assoc}
Map corresponding values. True if \arg{Assoc} is \arg{Assoc0} with \arg{Pred}
applied to all corresponding pairs of of values.
\end{description}

