Experimentado programador de lisp, esquema y clojure haciendo el cambio a elisp desde python para automatizar tareas básicas, cotidianas y básicas: me sorprendió enormemente lo siguiente en ielm
ELISP> (setq h2 (make-hash-table))
#s(hash-table size 65 test eql rehash-size 1.5 rehash-threshold 0.8 data ())
ELISP> (puthash "a" 1 h2)
1 (#o1, #x1, ?\C-a)
ELISP> (gethash "a" h2)
nil
eh? La clave y el valor parecen estar presentes:
ELISP> h2
#s(hash-table size 65 test eql rehash-size 1.5 rehash-threshold 0.8 data ("a" 1))
/ bofetadas en la frente. Debo estar perdiendo algo totalmente obvio. La información dice:
-- Function: gethash key table &optional default
This function looks up KEY in TABLE, and returns its associated
VALUE—or DEFAULT, if KEY has no association in TABLE.
estupendo. Veamos si podemos gethashdevolver algo más que nil:
ELISP> (gethash "a" h2 'fubar)
fubar
Guau. Ok, soy mucho más tonto de lo que pensaba. ¿Qué demonios estoy haciendo mal?

:testparámetro en tu ejemplo ...string-equalpodría tener algunas ventajas sobreequalsi sé que mi tabla hash tiene cadenas solo como claves. No estoy seguro de por qué elisp tiene ambosstring-equalyequal, ya queequalse puede usar en cualquier lugar questring-equalse pueda usar módulo, el hecho de questring-equalarroja errores de tipo cuando no le da cadenas. Tal vez ese es un comportamiento deseado.