gethash不适用于字符串键

时间:2014-02-03 11:22:31

标签: emacs elisp

在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不会返回它。

怎么了?

docs for hash table functions

2 个答案:

答案 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有许多不同形式的平等。您应该至少熟悉eqeqlequal=string-equal(别名string=)。