Quick pop quiz. In emacs lisp what does this expression evaluate to?
(let ((%h (make-hash-table))) (puthash "key" "value" %h) (gethash "key" %h))
Okay, put your hands down, the lispers at the back. Anyone else?
That’s right, the answer is nil.
"Eh nil? Is that the same as false? Why’s that?" you may be asking. The answer is that by default hash tables use eql as the comparison function. (eql "x" "x") evaluates to nil. (equal "x" "x") evaluates to t.
What you actually want is this.
(let ((%h (make-hash-table :test 'equal))) (puthash "key" "value" %h) (gethash "key" %h))
Quite why you would want a hash where you can’t retrieve a string key is beyond me. Okay, I guess it possibly makes sense if you consider symbols, but damn, it’s not right.
Anyway, no worries, I can fix it. I’ll only ever use my _h macro rather than using make-hash-table, puthash or gethash directly, and I’ll extend it to create hash tables using
(the original title for this page was Why do Emacs Lisp Hash Tables use Eql)