% -*- Mode: TeX -*- \beginsubsection{Hash-Table Operations} \Thenextfigure\ lists some \term{defined names} that are applicable to \term{hash tables}. The following rules apply to \term{hash tables}. %% 16.0.0 2 %% 16.0.0 4 \beginlist \itemitem{--} A \term{hash table} can only associate one value with a given key. If an attempt is made to add a second value for a given key, the second value will replace the first. Thus, adding a value to a \term{hash table} is a destructive operation; the \term{hash table} is modified. %% 16.0.0 5 \itemitem{--} There are four kinds of \term{hash tables}: those whose keys are compared with \funref{eq}, those whose keys are compared with \funref{eql}, those whose keys are compared with \funref{equal}, and \issue{HASH-TABLE-TESTS:ADD-EQUALP} those whose keys are compared with \funref{equalp}. \endissue{HASH-TABLE-TESTS:ADD-EQUALP} %% 16.0.0 6 \itemitem{--} \term{Hash tables} are created by \funref{make-hash-table}. \funref{gethash} is used to look up a key and find the associated value. New entries are added to \term{hash tables} using \macref{setf} with \funref{gethash}. \funref{remhash} is used to remove an entry. For example: \code (setq a (make-hash-table)) \EV # (setf (gethash 'color a) 'brown) \EV BROWN (setf (gethash 'name a) 'fred) \EV FRED (gethash 'color a) \EV BROWN, \term{true} (gethash 'name a) \EV FRED, \term{true} (gethash 'pointy a) \EV NIL, \term{false} \endcode %% 16.0.0 7 In this example, the symbols \f{color} and \f{name} are being used as keys, and the symbols \f{brown} and \f{fred} are being used as the associated values. The \term{hash table} has two items in it, one of which associates from \f{color} to \f{brown}, and the other of which associates from \f{name} to \f{fred}. %% 16.0.0 8 \itemitem{--} A key or a value may be any \term{object}. \issue{HASH-TABLE-SIZE:INTENDED-ENTRIES} % The following will be deleted. % % %% 16.0.0 9 % \itemitem{--} % A \term{hash table}'s size is the maximum number of entries % it can hold without collisions. Usually the actual capacity of % the table is somewhat less, since the hashing is not perfectly % collision-free. If so many entries are % added that the capacity is exceeded, the \term{hash table} % will automatically % grow, and the entries will be rehashed (new hash values will be % recomputed, and everything will be rearranged so that the fast hash % lookup still works). This is transparent to the caller; it all happens % automatically. \endissue{HASH-TABLE-SIZE:INTENDED-ENTRIES} %% 16.0.0 10 \itemitem{--} % The cases of \f{nil} as a value and no entry in the \term{hash table} % can be distinguished by the second value returned by \funref{gethash}. %% Reworded per Barmar: The existence of an entry in the \term{hash table} can be determined from the \term{secondary value} returned by \funref{gethash}. \endlist \displaythree{Hash-table defined names}{ clrhash&hash-table-p&remhash\cr gethash&make-hash-table&sxhash\cr hash-table-count&maphash&\cr } \endsubsection%{Hash-Table Operations} \beginsubsection{Modifying Hash Table Keys} \DefineSection{ModifyingHashKeys} \issue{HASH-TABLE-KEY-MODIFICATION:SPECIFY} The function supplied as the \kwd{test} argument to \funref{make-hash-table} specifies the `equivalence test' for the \term{hash table} it creates. An \term{object} is `visibly modified' with regard to an equivalence test if there exists some set of \term{objects} (or potential \term{objects}) which are equivalent to the \term{object} before the modification but are no longer equivalent afterwards. % If an \term{object} is used as a key in a \term{hash table} and is then visibly % modified with regard to the equivalence test of the \term{hash table}, then % using the \term{object} as a key in further operations on the \term{hash table} % has unspecified consequences. Moreover, this applies for other \term{objects} % which either are or were equivalent to the key object. Further, undoing the % modification does not remove this effect. If an \term{object} $O\sub 1$ is used as a key in a \term{hash table} $H$ and is then visibly modified with regard to the equivalence test of $H$, then the consequences are unspecified if $O\sub 1$, or any \term{object} $O\sub 2$ equivalent to $O\sub 1$ under the equivalence test (either before or after the modification), is used as a key in further operations on $H$. The consequences of using $O\sub 1$ as a key are unspecified even if $O\sub 1$ is visibly modified and then later modified again in such a way as to undo the visible modification. Following are specifications of the modifications which are visible to the equivalence tests which must be supported by \term{hash tables}. The modifications are described in terms of modification of components, and are defined recursively. Visible modifications of components of the \term{object} are visible modifications of the \term{object}. \beginsubsubsection{Visible Modification of Objects with respect to EQ and EQL} \DefineSection{VisModEQ} \DefineSection{VisModEQL} No \term{standardized} \term{function} is provided that is capable of visibly modifying an \term{object} with regard to \funref{eq} or \funref{eql}. \endsubsubsection%{Visible Modification of Objects with respect to EQ and EQL} \beginsubsubsection{Visible Modification of Objects with respect to EQUAL} \DefineSection{VisModEQUAL} As a consequence of the behavior for \funref{equal}, the rules for visible modification of \term{objects} not explicitly mentioned in this section are inherited from those in \secref\VisModEQL. \beginsubsubsubsection{Visible Modification of Conses with respect to EQUAL} Any visible change to the \term{car} or the \term{cdr} of a \term{cons} is considered a visible modification with regard to \funref{equal}. \endsubsubsubsection%{Visible Modification of Conses with respect to EQUAL} \beginsubsubsubsection{Visible Modification of Bit Vectors and Strings with respect to EQUAL} For a \term{vector} \oftype{bit-vector} or \oftype{string}, any visible change to an \term{active} \term{element} of the \term{vector}, or to the \term{length} of the \term{vector} (if it is \term{actually adjustable} or has a \term{fill pointer}) is considered a visible modification with regard to \funref{equal}. \endsubsubsubsection%{Visible Modification of Bit Vectors and Strings with respect to EQUAL} \endsubsubsection%{Visible Modification of Objects with respect to EQUAL} \beginsubsubsection{Visible Modification of Objects with respect to EQUALP} As a consequence of the behavior for \funref{equalp}, the rules for visible modification of \term{objects} not explicitly mentioned in this section are inherited from those in \secref\VisModEQUAL. \beginsubsubsubsection{Visible Modification of Structures with respect to EQUALP} Any visible change to a \term{slot} of a \term{structure} is considered a visible modification with regard to \funref{equalp}. \endsubsubsubsection%{Visible Modification of Structures with respect to EQUALP} \beginsubsubsubsection{Visible Modification of Arrays with respect to EQUALP} In an \term{array}, any visible change to an \term{active} \term{element}, to the \term{fill pointer} (if the \term{array} can and does have one), or to the \term{dimensions} (if the \term{array} is \term{actually adjustable}) is considered a visible modification with regard to \funref{equalp}. \endsubsubsubsection%{Visible Modification of Arrays with respect to EQUALP} \beginsubsubsubsection{Visible Modification of Hash Tables with respect to EQUALP} In a \term{hash table}, any visible change to the count of entries in the \term{hash table}, to the keys, or to the values associated with the keys is considered a visible modification with regard to \funref{equalp}. Note that the visibility of modifications to the keys depends on the equivalence test of the \term{hash table}, not on the specification of \funref{equalp}. \endsubsubsubsection%{Visible Modification of Hash Tables with respect to EQUALP} \endsubsubsection%{Visible Modification of Objects with respect to EQUALP} \beginsubsubsection{Visible Modifications by Language Extensions} \term{Implementations} that extend the language by providing additional mutator functions (or additional behavior for existing mutator functions) must document how the use of these extensions interacts with equivalence tests and \term{hash table} searches. \term{Implementations} that extend the language by defining additional acceptable equivalence tests for \term{hash tables} (allowing additional values for the \kwd{test} argument to \funref{make-hash-table}) must document the visible components of these tests. \endsubsubsection%{Visible Modifications by Language Extensions} % !!! Maybe consider making these things visible... % % Test Cases/Examples: % % (setf ht (make-hash-table :test #'eq)) % (setf a (cons 1 2)) % (setf (gethash a ht) 'win) % (setf (cdr a) 3) % (gethash a ht 'lose) => win t % % The same example with :test #'equal in the first line would be an error. % % The following example is not an error, because EQUAL does not examine the % components of general vectors: % % (setf ht (make-hash-table :test #'equal)) % (setf a (vector 1 2)) % (setf (gethash a ht) 'win) % (setf (aref a 1) 3) % (gethash a ht 'lose) => win t % % The following example is not an error, because EQUALP is limited by the % fill-pointer when examining the elements of a vector: % % (setf ht (make-hash-table :test #'equalp)) % (setf a (make-array 3 :fill-pointer 2 :initial-contents '(1 2 3))) % (setf (gethash a ht) 'win) % (setf (aref a 2) 4) % (gethash a ht 'lose) => win t % % The following example is an error, because EQUALP may examine the dimensions % of arrays: % % (setf ht (make-hash-table :test #'equalp)) % (setf a (make-array '(2 3) :adjustable t)) % (setf (gethash a ht) 'win) % (setf a (adjust-array a '(3 2))) % (gethash a ht 'lose) => `unspecified' % % The following example is not an error, because EQUALP is case insensitive: % % (setf ht (make-hash-table :test #'equalp)) % (setf a "ABC") % (setf (gethash a ht) 'win) % (setf (char a 0) #\a) % (gethash a ht 'lose) => win t % % The same example with :test #'equal in the first line would be an error. % \endissue{HASH-TABLE-KEY-MODIFICATION:SPECIFY} \endsubsection%{Modifying Hash Table Keys}