Оперативное значение, подкачивающее
>>> a = 10
>>> b = 5
>>> a, b
(10, 5)
>>> a, b = b, a
>>> a, b
(5, 10)
, правая сторона присвоения является выражением, которое создает новый кортеж. Левая сторона присвоения сразу распаковывает тот (не имеющий ссылки) кортеж к именам a
и b
.
После присвоения, новый кортеж является не имеющим ссылки и отмечен для сборки "мусора", и значения, связанные с a
и b
, были подкачаны.
, Как отмечено в учебный раздел Python по структурам данных ,
Примечание, что несколько присвоение являются действительно просто комбинацией упаковки кортежа и распаковки последовательности.
Вы всегда можете использовать для этого библиотеку Java, например одну из коллекций в Общие ресурсы Apache . TreeBidiMap реализует java.util.Map
, поэтому он может быть даже последовательным без каких-либо усилий.
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")
Некоторые вещи не будут работать, например assoc
и disoc
, поскольку они ожидают постоянных коллекций, а TreeBidiMap является изменяемым.
Если вы действительно хотите сделать это в родном Clojure, вы можете использовать метаданные для хранения хэша обратного направления. Это по-прежнему удвоит ваши требования к памяти и удвоит время для каждого добавления и удаления, но поиск будет достаточно быстрым и, по крайней мере, все будет объединено.
(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))
Вам, вероятно, придется реализовать кучу других функций, чтобы получить полную функциональность конечно. Не уверен, насколько осуществим этот подход.
user> (def x (assoc-bidi (make-bidi) :foo :bar))
#'user/x
user> (:foo x)
:bar
user> (getkey x :bar)
:foo