pourquoi gethash ne retournera-t-il pas la valeur de ma clé?

8

Programmeur expérimenté, lisp, schema, clojure passant à elisp de python pour automatiser les tâches de base de routine, quotidiennes: j'ai eu une énorme surprise de ce qui suit dans 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

hein? La clé et la valeur semblent être présentes:

ELISP> h2
#s(hash-table size 65 test eql rehash-size 1.5 rehash-threshold 0.8 data ("a" 1))

/ gifle le front. Je dois manquer quelque chose de totalement évident. L'info dit:

-- 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.

génial. Voyons voir si nous pouvons obtenir gethashde retourner autre chose que nil:

ELISP> (gethash "a" h2 'fubar) 
fubar

sensationnel. Ok, je suis beaucoup plus bête que je ne le pensais. Qu'est-ce que je fais de mal?

Reb.Cabin
la source

Réponses:

13

Le test d'appartenance par défaut pour une table de hachage est eql. Si vous souhaitez utiliser une chaîne comme clé, définissez-la à la equalplace:

(setf hash (make-hash-table :test #'equal))
(puthash "a" 1 hash)
(gethash "a" hash)                      ; ==> 1

Pour référence, voici la partie pertinente de la docstring:

make-hash-table est une fonction intégrée au `code source C '.

(make-hash-table &rest KEYWORD-ARGS)

Créez et renvoyez une nouvelle table de hachage.

Les arguments sont spécifiés sous forme de paires mot-clé / argument. Les arguments suivants sont définis:

:testTEST - TEST doit être un symbole qui spécifie comment comparer les clés. La valeur par défaut est eql. Les tests sont pré - définies eq, eqlet equal. Les fonctions de test et de hachage fournies par l'utilisateur peuvent être spécifiées via define-hash-table-test.

Dan
la source
Je suppose que techniquement, vous ne passez pas un symbole comme :testparamètre dans votre exemple ...
Sean
string-equalpourrait avoir quelques avantages equalsi je sais que ma table de hachage a des chaînes uniquement comme clés. Je ne sais pas pourquoi elisp a les deux string-equalet equal, parce que equalpeut être utilisé n'importe quel endroit qui string-equalpeut être utilisé modulo le fait que string-equaljette des erreurs de type lorsque vous ne lui donnez pas de chaînes. C'est peut-être un comportement souhaité.
Reb.Cabin