【问题标题】:What is the idiomatic way to pop a PersistentQueue in a ref?在 ref 中弹出 PersistentQueue 的惯用方法是什么?
【发布时间】:2011-06-20 22:18:14
【问题描述】:

在 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 返回已经弹出的队列的事务中值,因此您不能只自己进行更改。

【问题讨论】:

  • 添加到队列的惯用方法是:(dosync (alter pq conj new-item))

标签: concurrency clojure queue


【解决方案1】:

您的 dosync 主体可以使用 Common Lisp 的 prog1 宏来简化,尽管核心 Clojure 似乎缺少它。有一个简单的实现 on the Google group,以及一些关于如何在 Clojure 中使其成为函数(而不是宏)的讨论。

【讨论】:

    【解决方案2】:

    除了抽象出你的 dosync 的主体之外,我想不出更惯用的方法了。

    但是,如果您想玩特技,您可以尝试off-by-one hack:始终将 PQ 的头部视为垃圾(它包含先前弹出的项目)。由此可见你可以重写qpop

    (defn qpop [queue-ref]
      (peek (alter queue-ref pop))
    

    它会增加对空虚的特殊检查(特别是当你 conj 时)。这也意味着保持对项目的引用比它应该保持的时间更长(但是,如果你查看 PQ 的 impl,你会发现它本身可能会保持对弹出项目的引用太久,所以活跃度已经很模糊了)。

    我使用了这个 hack here

    【讨论】:

    • 你是个可怕的家伙 cgrand。 [我的意思是作为一种恭维。 :)]
    猜你喜欢
    • 1970-01-01
    • 2015-05-11
    • 2011-05-04
    • 2012-11-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-19
    • 2014-01-28
    相关资源
    最近更新 更多