2010-07-15 22 views
6

Ho un codice come questo. Posso eseguire questo in repl ma non posso dalla riga di comando. Credo di avere un problema di valutazione pigro.Problema di valutazione pigro


; items.clj 

(def items (ref [])) 

(defn init-items [] 
    (map 
    #(dosync 
     (alter items conj %)) 
    ["foo" "bar" "baz" ])) 

(init-items) 
(println (first @items)) 

$ java -jar clojure.jar items.clj 
$ nil 

saluti.

risposta

4

Trovato!

solution

Clojure non è motivato per eseguire la funzione map in init-items perché non c'è alcun risultato restituito. L'ho avvolto in un doall per forzare l'esecuzione, e presto.

+0

ho lavorato. Molte grazie. – Osman

+3

In realtà 'dorun' è più adatto a questo caso (' doall' tiene sulla testa del seq esso lo avvolge e lo restituisce, mentre 'dorun' lo scarta passo dopo passo e infine restituisce' nil' - quindi è più adatto a codice side-effecty). –

+0

@Michal: hai assolutamente ragione, ovviamente. Mi sono dilungato un po 'con Clojure ma non ho mai raggiunto un'alta competenza, e ora, purtroppo, anche questo comincia a arrugginire. Grazie per la correzione! –

4

Alcune alternative:

Se si desidera aggiungere un po 'di elementi a una raccolta tenuto in un Ref, a partire da una transazione per articolo e conj ing separatamente è un po' uno spreco. Invece, si potrebbe fare

(defn init-items [] 
    (dosync (alter items into ["foo" "bar" "baz"]))) 

Se si ha qualche ragione per farlo in un modo unico elemento-per-passo, penso che l'approccio più idiomatica e conveniente sarebbe attualmente quella di utilizzare doseq:

(defn init-items [] 
    (doseq [item ["foo" "bar" "baz"]] 
    (dosync (alter items conj item)))) 

(Oppure si potrebbe spostare avvolgere l'intero doseq in un dosync e non utilizzare dosync nel corpo 's la doseq.)

Problemi correlati