I've a code like this. I can run this in repl but can't from command line. I guess i've a lazy evaluation problem.
; 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
Regards.
Got it!
solution
Clojure is not motivated to run the map
function in init-items
because there's no result returned. I wrapped that into a doall
to force execution, and presto.
Some alternatives:
If you just want to add a bunch of items to a collection held in a Ref, starting one transaction per item and conj
ing them separately is a bit wasteful. Instead, you could do
(defn init-items []
(dosync (alter items into ["foo" "bar" "baz"])))
If you do have some reason to do it in a one-item-per-step fashion, I think the most idiomatic and convenient approach would currently be to use doseq
:
(defn init-items []
(doseq [item ["foo" "bar" "baz"]]
(dosync (alter items conj item))))
(Or you could move wrap the entire doseq
in a dosync
and not use dosync
in the doseq
's body.)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With