2010-07-15 13 views
6

Tengo un código como este. Puedo ejecutar esto en repl pero no puedo desde la línea de comando. Supongo que tengo un problema de evaluación perezosa.Problema de evaluación diferida


; 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 

Saludos.

Respuesta

4

¡Lo tengo!

solution

Clojure no está motivado para ejecutar la función map en init-items porque no hay resultado devuelto. Envolví eso en un doall para forzar la ejecución, y listo.

+0

trabajé. Muchas gracias. – Osman

+3

En realidad, 'dorun' se adapta mejor a este caso (' doall' se aferra a la cabeza del seq y lo devuelve, mientras que 'dorun' lo descarta paso a paso y finalmente devuelve' nil', por lo que es más adecuado código de efecto secundario). –

+0

@Michal: Tienes toda la razón, por supuesto. He incursionado un poco con Clojure pero nunca alcancé una gran habilidad, y ahora, lamentablemente, incluso eso está empezando a oxidarse. ¡Gracias por la corrección! –

4

Algunas alternativas:

Si lo que desea es añadir un montón de elementos a una colección que tuvo lugar en un Referencia, a partir de una transacción por elemento y conj ing ellos por separado es un poco desperdicio. En su lugar, se podría hacer

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

Si usted tiene alguna razón para hacerlo de una manera un elemento-por-paso, creo que el enfoque más idiomática y conveniente sería actualmente de usar doseq:

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

(O puede mover toda la envoltura doseq en un dosync y no utilizar dosync en el cuerpo del doseq 's.)

Cuestiones relacionadas