[英]Common Lisp SXHASH and nested lists
標准說(equal xy) implies (= (sxhash x) (sxhash y))
。 讓我們檢查一下:
(defun sxhash-test ()
(let ((obj1 (list 1 2 (list 1 1)))
(obj2 (list 1 2 (list 1 2))))
(format t "are objects equal?: ~a~%" (equal obj1 obj2)) ;; => NIL
(format t "are their hashes equal?: ~a~%"(= (sxhash obj1) (sxhash obj2))))) ;; => T
equal
函數按預期工作,但sxhash
沒有。 你能解釋一下我做錯了什么嗎? 我使用 SBCL 2.1.9。
謝謝你。
觀察到這種效果的原因是值要equal
需要兩件事:
測試的兩個列表具有相同的哈希值,因為 sxhash 不遵循嵌套。 事實上,兩個結構將始終具有相同的哈希值。
(sxhash (list 1 2 3)); => 3971322300187561939
(sxhash (list 1 2 3)); => 3971322300187561939 (so, repeatable)
(sxhash (list 1 2 3 (list 4))) ; => 3180777146619076709
(sxhash (list 1 2 3 (list 5))) ; => 3180777146619076709 (ok ...)
至於相等的地址,如果我創建兩個值,例如'a
它們實際上是一個具有一個地址的項目,並且僅在第一次看到時存儲。 而(list 1 2 (list 1 1))
和(list 1 2 (list 1 2))
是不同的東西並且存儲在不同的地址。
(sb-kernel:get-lisp-obj-address 'a) ; => 68772678703
(sb-kernel:get-lisp-obj-address 'a) ; => 68772678703 (same...)
(sb-kernel:get-lisp-obj-address (list 1 2 3 (list 4))) ; => 68772925863
(sb-kernel:get-lisp-obj-address (list 1 2 3 (list 5))) ; => 68772805335
使用 sxhash 測試這兩個列表是否相等,但由於地址不同而失敗。
sxhash
必須滿足四個要求:
equal
對象(因此是eql
、 eq
對象,但不一定是equalp
將具有相同的sxhash
值;sxhash
值在單個圖像的生命周期內不得更改,除非該對象的更改方式使其不equal
更改前的副本;sxhash
值在每個圖像中必須相同。sxhash
計算必須始終終止。(“成為一個好的哈希碼”還有另一個模糊的要求)。
(1)指的是兩個對象哪些不是equal
可以具有相同的代碼,但也可以沒有,但兩個對象它們是equal
必須具有相同的值。 一個可怕但可能的sxhash
實現是:
(defun sxhash/terrible (it)
(declare (ignore it))
0)
這未能通過“成為一個好的哈希碼”測試,但這並不是真正可以強制執行的。
您所看到的是兩個不equal
對象確實具有相同的sxhash
值:這很好。
實際上,(1) 和 (4) 意味着如果一個實現要以sxhash
圖的方式計算sxhash
上的 sxhash,那么它必須非常小心:它要么需要發生檢查,要么只需要深入。
然而, sxhash
很有可能會下降到 cons 樹中。 舉個例子, LispWorks 就是這樣做的:
> (sxhash '(1 2 3))
11890816076270616
> (sxhash '(1 2 3 (4)))
369102953153702944
> (sxhash '(1 2 3 (4)))
740958182301008344
> (sxhash '(1 2 3 (5)))
740958455027237144
> (sxhash '(1 2 3 (5 6)))
741326672350173760
> (sxhash '(1 2 3 (5 (6))))
925006242171775434
同樣, sxhash
將 gigen 結構類(或standard-class
的給定實例)的所有實例視為具有相同的值也是很有道理的,因為這樣的對象的地址不是常量,並且沒有明顯的地方來存儲不燒內存的哈希碼。 但這絕不是一個要求。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.