Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Lazy evaluation problem

Tags:

clojure

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.

like image 462
Osman Avatar asked Jul 15 '10 15:07

Osman


2 Answers

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.

like image 135
Carl Smotricz Avatar answered Sep 21 '22 11:09

Carl Smotricz


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 conjing 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.)

like image 36
Michał Marczyk Avatar answered Sep 21 '22 11:09

Michał Marczyk