當在結構上使用Common Lisp sxhash
函數時,我得到了所有結構的相同值(在SBCL中只有相同類型的結構)。例如,下面的代碼打印出兩個具有相同值的整數列表。爲什麼`sxhash`爲所有結構返回一個常量?
(progn
(defstruct foo
data)
(print (mapcar #'sxhash (loop for i below 10 collect (make-foo :data i))))
(defstruct bar
data)
(print (mapcar #'sxhash (loop for i below 10 collect (make-bar :data i)))))
;;; Allegro
(319 319 319 319 319 319 319 319 319 319)
(319 319 319 319 319 319 319 319 319 319)
;;; SBCL
(22591133455133788 22591133455133788 22591133455133788 22591133455133788
22591133455133788 22591133455133788 22591133455133788 22591133455133788
22591133455133788 22591133455133788)
(21321591953876048 21321591953876048 21321591953876048 21321591953876048
21321591953876048 21321591953876048 21321591953876048 21321591953876048
21321591953876048 21321591953876048)
我已經在這兩個Allegro Lisp和SBCL和都返回(不同)爲所有結構(在SBCL相同類型)常量嘗試這個。對鏈接sxhash
Hyperspec頁有以下語句:
對於任何兩個對象,x和y,這兩者都是位向量,字符,conses之外,數字路徑名,字符串或符號,以及哪個 類似,(sxhash x)和(sxhash y)產生相同的數學 值,即使x和y存在於相同 實現的不同Lisp圖像中。請參見第3.2.4節(編譯文件中的文字對象)。
對象的散列碼在單個會話中始終是相同的,前提是該對象不會被可視地修改爲關於 與等效性測試相等。參見18.1.2節(修改哈希表 表鍵)。
後者語句未指定,但似乎暗示,這將是明智的這兩個結構不屬於equal
會有不同的哈希碼(模碰撞)。但是,第一段中的結構可疑地缺失。起初,我將這寫成了Allegro Lisp中的一個錯誤,但現在我發現它有兩種不同的實現方式,我認爲必須有一些關於我不明白的規範。
一個保證是,如果'(等於x y)'那麼'(=(sxhash x)(sxhash y))'。我似乎記得(但我可能會混淆comp.lang.lisp和hyperspec),你看到的並不少見,因爲有不同的東西會有相同的sxhash散列值。 – Vatine
@Vantine是的,看起來至少SBCL和Allegro是出於內存佔用的原因。他們不能使用內存地址,因爲它會改變,並且hyperspec要求'sxhash'對於相同實現中的類似對象是相同的。此外,他們不能做遞歸遍歷(安全),因爲對象可能會發生變異。 – asm