有没有更简单的方法在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))
Run Code Online (Sandbox Code Playgroud)
写它的另一种方法是:
(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))
Run Code Online (Sandbox Code Playgroud)
这似乎更糟糕.
无论如何,我有一个使用原子排队很多的代码,并使用前一种方法使代码真的令人困惑,我希望有类似的东西:
(swap! queue (fn [queue] (AtomSwapResult. atom-value return-value))
Run Code Online (Sandbox Code Playgroud)
或交换中的一些类似机制!函数,因为它似乎是你想要经常做的事情(甚至不限于排队,我已经遇到了几个其他用例,其中返回一个不同的值是有用的,例如,交换的旧值out)并且它不会打破原子/交换!语义.
有没有办法在Clojure中做到这一点?
kot*_*rak 16
(defn dequeue!
[queue]
(loop []
(let [q @queue
value (peek q)
nq (pop q)]
(if (compare-and-set! queue q nq)
value
(recur)))))
(def queue (atom clojure.lang.PersistentQueue/EMPTY))
(swap! queue conj :foo)
(swap! queue conj :bar)
(seq @queue)
(dequeue! queue)
(seq @queue)
Run Code Online (Sandbox Code Playgroud)