簡體   English   中英

Common Lisp SXHASH 和嵌套列表

[英]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需要兩件事:

  1. 這兩個值相同,意味着具有相同的哈希值。
  2. 這兩個值具有相同的地址

測試的兩個列表具有相同的哈希值,因為 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 ...)

為什么`sxhash` 為所有結構返回一個常量?

至於相等的地址,如果我創建兩個值,例如'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必須滿足四個要求:

  1. equal對象(因此是eqleq對象,但不一定是equalp將具有相同的sxhash值;
  2. 對象的sxhash值在單個圖像的生命周期內不得更改,除非該對象的更改方式使其不equal更改前的副本;
  3. 具有明確定義的圖像之間相似性概念的各種類型的對象,則它們的sxhash值在每個圖像中必須相同。
  4. 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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM