извлечение из Есть более простой способ, чтобы написать этот код в Clojure:Clojure своп! атом
(def queue (atom {:top nil :queue PersistentQueue/EMPTY}))
(swap! queue #(hash-map :top nil :queue (conj (:queue %) "foo")))
(let [{:keys [top]} (swap! queue
#(hash-map
:top (peek (:queue %))
:queue (pop (:queue %))))]
(println top))
альтернативный способ написать это будет:
(def queue (atom PersistentQueue/EMPTY))
(swap! queue conj "foo")
(let [top (atom nil)]
(swap! queue
(fn [queue]
(reset! top (peek queue))
(pop queue)))
(println @top))
Это кажется еще хуже.
Во всяком случае у меня есть код, который использует атомы для очередями много и используя прежний подход делает код действительно сбивает с толку, я ожидал бы, чтобы было что-то вроде:
(swap! queue (fn [queue] (AtomSwapResult. atom-value return-value))
или какой-либо аналогичного механизма в замена! потому что это похоже на то, что вы хотели бы часто делать (даже не ограничиваясь очередью, я ударил несколько других случаев использования, когда было бы полезно вернуть другое значение, например, старое значение, которое было заменено) и он не разбивает атом/своп! семантика.
Есть ли способ сделать это в Clojure?
лол я написал CAS один первый раз, когда я столкнулся с проблемой, но думал, что это было слишком громоздким, а не рассматривать его в отделение функции - чувство довольно немой прямо сейчас :) –
Обратите внимание, что вы, вероятно, не можете отличить nils от очереди и nils от пустой очереди. Проверка с 'count' до' dequeue! 'Не является потокобезопасной. Поэтому будьте осторожны с ловушками. – kotarak
Yup - помните эту часть - если кто-то заботится - первое решение выше может быть изменено, чтобы проверить, присутствует ли верхний ключ, и это пустой сигнал очереди. –