diff options
| author | Craig Jennings <c@cjennings.net> | 2024-04-07 13:41:34 -0500 |
|---|---|---|
| committer | Craig Jennings <c@cjennings.net> | 2024-04-07 13:41:34 -0500 |
| commit | 754bbf7a25a8dda49b5d08ef0d0443bbf5af0e36 (patch) | |
| tree | f1190704f78f04a2b0b4c977d20fe96a828377f1 /devdocs/elisp/defining-hash.html | |
new repository
Diffstat (limited to 'devdocs/elisp/defining-hash.html')
| -rw-r--r-- | devdocs/elisp/defining-hash.html | 36 |
1 files changed, 36 insertions, 0 deletions
diff --git a/devdocs/elisp/defining-hash.html b/devdocs/elisp/defining-hash.html new file mode 100644 index 00000000..355e7773 --- /dev/null +++ b/devdocs/elisp/defining-hash.html @@ -0,0 +1,36 @@ + <h3 class="section">Defining Hash Comparisons</h3> <p>You can define new methods of key lookup by means of <code>define-hash-table-test</code>. In order to use this feature, you need to understand how hash tables work, and what a <em>hash code</em> means. </p> <p>You can think of a hash table conceptually as a large array of many slots, each capable of holding one association. To look up a key, <code>gethash</code> first computes an integer, the hash code, from the key. It can reduce this integer modulo the length of the array, to produce an index in the array. Then it looks in that slot, and if necessary in other nearby slots, to see if it has found the key being sought. </p> <p>Thus, to define a new method of key lookup, you need to specify both a function to compute the hash code from a key, and a function to compare two keys directly. The two functions should be consistent with each other: that is, two keys’ hash codes should be the same if the keys compare as equal. Also, since the two functions can be called at any time (such as by the garbage collector), the functions should be free of side effects and should return quickly, and their behavior should depend on only on properties of the keys that do not change. </p> <dl> <dt id="define-hash-table-test">Function: <strong>define-hash-table-test</strong> <em>name test-fn hash-fn</em> +</dt> <dd> +<p>This function defines a new hash table test, named <var>name</var>. </p> <p>After defining <var>name</var> in this way, you can use it as the <var>test</var> argument in <code>make-hash-table</code>. When you do that, the hash table will use <var>test-fn</var> to compare key values, and <var>hash-fn</var> to compute a hash code from a key value. </p> <p>The function <var>test-fn</var> should accept two arguments, two keys, and return non-<code>nil</code> if they are considered the same. </p> <p>The function <var>hash-fn</var> should accept one argument, a key, and return an integer that is the hash code of that key. For good results, the function should use the whole range of fixnums for hash codes, including negative fixnums. </p> <p>The specified functions are stored in the property list of <var>name</var> under the property <code>hash-table-test</code>; the property value’s form is <code>(<var>test-fn</var> <var>hash-fn</var>)</code>. </p> +</dd> +</dl> <dl> <dt id="sxhash-equal">Function: <strong>sxhash-equal</strong> <em>obj</em> +</dt> <dd> +<p>This function returns a hash code for Lisp object <var>obj</var>. This is an integer that reflects the contents of <var>obj</var> and the other Lisp objects it points to. </p> <p>If two objects <var>obj1</var> and <var>obj2</var> are <code>equal</code>, then <code>(sxhash-equal <var>obj1</var>)</code> and <code>(sxhash-equal <var>obj2</var>)</code> are the same integer. </p> <p>If the two objects are not <code>equal</code>, the values returned by <code>sxhash-equal</code> are usually different, but not always; once in a rare while, by luck, you will encounter two distinct-looking objects that give the same result from <code>sxhash-equal</code>. </p> <p><b>Common Lisp note:</b> In Common Lisp a similar function is called <code>sxhash</code>. Emacs provides this name as a compatibility alias for <code>sxhash-equal</code>. </p> +</dd> +</dl> <dl> <dt id="sxhash-eq">Function: <strong>sxhash-eq</strong> <em>obj</em> +</dt> <dd> +<p>This function returns a hash code for Lisp object <var>obj</var>. Its result reflects identity of <var>obj</var>, but not its contents. </p> <p>If two objects <var>obj1</var> and <var>obj2</var> are <code>eq</code>, then <code>(sxhash-eq <var>obj1</var>)</code> and <code>(sxhash-eq <var>obj2</var>)</code> are the same integer. </p> +</dd> +</dl> <dl> <dt id="sxhash-eql">Function: <strong>sxhash-eql</strong> <em>obj</em> +</dt> <dd> +<p>This function returns a hash code for Lisp object <var>obj</var> suitable for <code>eql</code> comparison. I.e. it reflects identity of <var>obj</var> except for the case where the object is a bignum or a float number, in which case a hash code is generated for the value. </p> <p>If two objects <var>obj1</var> and <var>obj2</var> are <code>eql</code>, then <code>(sxhash-eql <var>obj1</var>)</code> and <code>(sxhash-eql <var>obj2</var>)</code> are the same integer. </p> +</dd> +</dl> <p>This example creates a hash table whose keys are strings that are compared case-insensitively. </p> <div class="example"> <pre class="example">(defun case-fold-string= (a b) + (eq t (compare-strings a nil nil b nil nil t))) +(defun case-fold-string-hash (a) + (sxhash-equal (upcase a))) + +(define-hash-table-test 'case-fold + 'case-fold-string= 'case-fold-string-hash) + +(make-hash-table :test 'case-fold) +</pre> +</div> <p>Here is how you could define a hash table test equivalent to the predefined test value <code>equal</code>. The keys can be any Lisp object, and equal-looking objects are considered the same key. </p> <div class="example"> <pre class="example">(define-hash-table-test 'contents-hash 'equal 'sxhash-equal) + +(make-hash-table :test 'contents-hash) +</pre> +</div> <p>Lisp programs should <em>not</em> rely on hash codes being preserved between Emacs sessions, as the implementation of the hash functions uses some details of the object storage that can change between sessions and between different architectures. </p><div class="_attribution"> + <p class="_attribution-p"> + Copyright © 1990-1996, 1998-2022 Free Software Foundation, Inc. <br>Licensed under the GNU GPL license.<br> + <a href="https://www.gnu.org/software/emacs/manual/html_node/elisp/Defining-Hash.html" class="_attribution-link">https://www.gnu.org/software/emacs/manual/html_node/elisp/Defining-Hash.html</a> + </p> +</div> |
