Vous pouvez toujours utiliser une bibliothèque Java pour cela, comme l'une des collections de Apache commons. TreeBidiMap implémente java.util.Map
donc c'est même seq-capable sans aucun effort.
user> (def x (org.apache.commons.collections.bidimap.TreeBidiMap.))
#'user/x
user> (.put x :foo :bar)
nil
user> (keys x)
(:foo)
user> (.getKey x :bar)
:foo
user> (:foo x)
:bar
user> (map (fn [[k v]] (str k ", " v)) x)
(":foo, :bar")
Certaines choses ne fonctionnent pas bien, comme assoc
et dissoc
, car ils attendent de collections persistantes et TreeBidiMap est mutable.
Si vous voulez vraiment le faire en Clojure natif, vous pouvez utiliser des métadonnées pour contenir le hachage en sens inverse. Cela va encore doubler vos besoins en mémoire et doubler le temps pour chaque ajout et suppression, mais les recherches seront assez rapides et au moins tout est regroupé.
(defn make-bidi []
(with-meta {} {}))
(defn assoc-bidi [h k v]
(vary-meta (assoc h k v)
assoc v k))
(defn dissoc-bidi [h k]
(let [v (h k)]
(vary-meta (dissoc h k)
dissoc v)))
(defn getkey [h v]
((meta h) v))
Vous devrez probablement mettre en œuvre un tas d'autres fonctions pour obtenir toutes les fonctionnalités bien sûr. Je ne suis pas certain de la faisabilité de cette approche.
user> (def x (assoc-bidi (make-bidi) :foo :bar))
#'user/x
user> (:foo x)
:bar
user> (getkey x :bar)
:foo
Merci, c'est utile. Je préférerais avoir une option native clojure, donc votre deuxième idée est quelque chose que je pourrais essayer. –