Concurrency 在ref中弹出PersistentQueue的惯用方法是什么?

Concurrency 在ref中弹出PersistentQueue的惯用方法是什么?,concurrency,clojure,queue,Concurrency,Clojure,Queue,给定ref中的PersistentQueue: (def pq (ref clojure.lang.PersistentQueue/EMPTY)) 弹出队列并获得结果的惯用方法是什么 我对你的批评的最好尝试是: (defn qpop [queue-ref] (dosync (let [item (peek @queue-ref)] (alter queue-ref pop) item)) alter返回已经弹出的队列的in事务

给定ref中的PersistentQueue:

(def pq (ref clojure.lang.PersistentQueue/EMPTY))
弹出队列并获得结果的惯用方法是什么

我对你的批评的最好尝试是:

(defn qpop [queue-ref]
    (dosync 
        (let [item (peek @queue-ref)]
          (alter queue-ref pop)
          item))

alter返回已经弹出的队列的in事务值,因此您不能只执行alter本身

除了把dosync的主体抽象出来,我想不出更地道的东西了

然而,如果你是一个特技演员,你可以试着用一个HAK/<强>关闭:总是把PQ的头当作垃圾(它包含以前弹出的项目)。因此,您可以重写

qpop

(defn qpop [queue-ref]
  (peek (alter queue-ref pop))
它会增加对空性的特殊检查(特别是当您连接时)。它还意味着保留对项目的引用的时间比它应该保留的时间长(但是,如果你查看PQ的impl,你会发现,通过itsef,它可能会保留对弹出项目的引用太长,因此活动性已经很模糊)


我使用了这个技巧。

可以使用Common Lisp的宏简化dosync主体,尽管core Clojure似乎缺少它。这里有一个简单的实现,并讨论了如何在Clojure中将其变成函数(而不是宏)。

添加到队列的惯用方法是:(dosync(alter pq conj new item))你是一个可怕的家伙。[我的意思是作为一种恭维。]