123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267 |
- % -*- 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 #<HASH-TABLE EQL 0/120 32536573>
- (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}
|