Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the idiomatic way to pop a PersistentQueue in a ref?

Given a PersistentQueue in a ref:

(def pq (ref clojure.lang.PersistentQueue/EMPTY))

What is the idiomatic way to pop the queue and get the result?

My best attempt for your critique:

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

alter returns the in-transaction value of the queue which is popped already, so you can't just do the alter by itself.

like image 740
Alex Miller Avatar asked Feb 03 '11 19:02

Alex Miller


2 Answers

I can't think of something more idiomatic short of abstracting the body of your dosync away.

However if you are in for a stunt, you can try the off-by-one hack: always consider the head of the PQ as garbage (it contains the previously popped item). It follows that you can rewrite qpop:

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

It incurs adding special checks for emptiness (in particular when you conj). It also means keeping a reference to the item around for longer than it should (however if you look at the impl of PQ you'll see that by itsef it may keep references to popped items for too long, so liveness is already murky).

I used this hack here.

like image 75
cgrand Avatar answered Sep 22 '22 13:09

cgrand


Your dosync body could be simplified using Common Lisp's prog1 macro, although core Clojure seems to lack it. There is a straightforward implementation on the Google group, along with some discussion on how you can make it a function (instead of a macro) in Clojure.

like image 1
Jouni K. Seppänen Avatar answered Sep 21 '22 13:09

Jouni K. Seppänen