【问题标题】:Clojure remove first(or last) element of vector inside refClojure删除ref内向量的第一个(或最后一个)元素
【发布时间】:2013-10-16 13:46:50
【问题描述】:

我需要的是简单的队列,我可以在其中放置任务并从工作人员那里一个接一个地检索它们(不维护任务的顺序)。

我是这样写的:

;; Definition
(def q (ref []))

;; Put
(defn put-in-queue [i]
  (dosync (alter q conj i)))

;; Get
(defn get-from-queue []
  (dosync
    (let [v (peek q)]
      (alter q pop)
      v)))

这是正确的解决方案吗? (也许这个任务也有更好的解决方案)

【问题讨论】:

    标签: concurrency clojure atomic


    【解决方案1】:

    你应该使用clojure.lang.PersistentQueue,适合这项工作的工具等等:)。

    下面的示例“借用”自Hidden features of Clojure

    user> (-> (clojure.lang.PersistentQueue/EMPTY)
              (conj 1 2 3)
              pop)
    (2 3)
    

    详情请参阅the remainder of that answer

    【讨论】:

      【解决方案2】:

      正确的解决方案可能是使用java.util.concurrent 队列,很可能是java.util.concurrent.LinkedBlockingQueuej.u.c 队列很健壮,非常适合任务并且在 Clojure 中工作得很好。

      请参阅my answerProducer consumer with qualifications SO 问题,了解以两种方式实现的具有 5 个生产者、2 个消费者和一个有限大小队列的方案以进行比较:第一种是c.l.PersistentQueue,第二种是j.u.c.LinkedBlockingQueue

      【讨论】:

        【解决方案3】:

        正如 dsm 指出的那样,当您需要队列时,请使用队列,而对于您确实需要向量并希望将内容添加到末尾并从前面删除它们的时候,subvecconj 是向量上的两个 O(1) 函数。

        user> (subvec [1 2 3] 1)
        [2 3]
        user> (conj [1 2 3] 4)
        [1 2 3 4]
        user> (-> [] (conj 1 2) (conj 3) (subvec 1))
        

        【讨论】:

        • 问题是关于多线程环境,而不仅仅是subvec。
        • clojure.core/subvec 保留底层向量,因此这将阻止所有条目无限期地符合 GC 条件。 (相比之下,clojure.core.rrb-vector/subvec 确实执行了一个真正的切片,丢弃了给定索引范围之外的条目。)
        猜你喜欢
        • 2012-03-06
        • 2012-08-20
        • 2011-04-14
        • 2014-08-22
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-11-21
        • 2011-06-06
        相关资源
        最近更新 更多