在elisp中研究哈希表,我试着写一个简单的例子:
(setq animals (make-hash-table))
(puthash "tiger" 120 animals)
(gethash "tiger" animals)
当我逐行执行时,调用gethash
会返回nil
,尽管如此,当我评估动物符号时,emacs会打印出来:
#s(hash-table size 65 test eql rehash-size 1.5 rehash-threshold
0.8 data ("tiger" 120 ...))
所以,“老虎”就在那里,但是由于某种原因,gethash不会返回它。
怎么了?
答案 0 :(得分:10)
哈希表的默认测试是eql
。每次键入字符串时,都会创建一个不同的字符串,因此它们彼此不是eql
。
(eql "tiger" "tiger") => nil
您需要使用equal
作为测试:
(setq animals (make-hash-table :test 'equal))
或者使用符号代替字符串作为表格中的键;由于符号是固定的,因此键入相同的符号名称两次会产生eql
个对象。
答案 1 :(得分:1)
当Emacs 打印哈希表并且你可以在其中看到"tiger"
时,它只显示真正的lisp的打印表示该结构中的对象和打印的表示可能不明确。
字符串对象的打印表示是其值,因此具有相同值的两个字符串对象具有相同的打印表示,因此,一旦打印,就无法区分它们。
您正在查看添加到表中的“tiger”字符串对象的打印表示,但这与您在下一行中查询的字符串对象不同。
lisp阅读器在读取代码时创建这些对象,每次读取字符串时都会创建一个新的字符串对象。正如Barmar指出的那样,符号表现不同,因为它们是由lisp阅读器 interned ,因此它总是“读取”同一个对象。字符串的情况类似于未处理符号的情况 - 您可能会发现this related discussion有用。
当然,lisp有许多不同形式的平等。您应该至少熟悉eq
,eql
,equal
,=
和string-equal
(别名string=
)。