2011-02-03 11 views
12

Dato un PersistentQueue in un ref:Qual è il modo idiomatico di inserire un PersistentQueue in un riferimento?

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

Qual è il modo idiomatico per estrarre la coda e ottenere il risultato?

mio miglior tentativo per la vostra critica:

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

restituisce modificare il valore di transazione della coda che è spuntato già, quindi non si può solo fare l'alter da solo.

+0

Idiomatico per l'aggiunta alla coda sarebbe: (dosync (alter pq conj new-item)) –

risposta

5

Non riesco a pensare a qualcosa di più idiomatico a corto di astrarre il corpo del tuo dosync.

Tuttavia, se ci si trova in una bravata, si può provare il off-by-one incidere: considerare sempre la testa del PQ come spazzatura (che contiene l'elemento precedentemente spuntato). Ne consegue che è possibile riscrivere qpop:

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

Esso comporta l'aggiunta di controlli speciali per il vuoto (in particolare quando si conj). Significa anche mantenere un riferimento all'oggetto in giro più a lungo di quanto dovrebbe (tuttavia se guardi l'impl di PQ vedrai che con esso potrebbe mantenere i riferimenti agli elementi spuntati troppo a lungo, quindi la vividezza è già torbida).

Ho usato questo trucco here.

+0

Sei un tizio terrificante. [Intendo questo come un complimento. :)] –

1

Il tuo corpo dosync può essere semplificato utilizzando la macro prog1 del Common Lisp, anche se il core Clojure sembra mancare. C'è un'implementazione diretta on the Google group, insieme ad alcune discussioni su come puoi renderlo una funzione (invece di una macro) in Clojure.

+0

grazie, buon consiglio. –

Problemi correlati