% 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 association 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}. \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. Does \textit{not} validate that keys are sufficiently instantiated to ensure the tree remains valid if a key is further instantiated. \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}