I need to create and populate an ArrayList in clojure and pass it to an Java API. Can someone help explain why there is a difference in the below two approaches (and why one of them doesn't work).
;;; this works
(defn make-an-array-list []
(let [alist (java.util.ArrayList.)]
(loop [x 0] (when (< x 6) (.add alist x) (recur (inc x)))) alist))
;;; ==> [0 1 2 3 4 5]
;;; this does not work
(defn make-an-array-list2 []
(let [alist (java.util.ArrayList.)]
(for [n (range 6)] (.add alist n)) alist))
;;; ==> []
Or, any suggestion in stead of the above approach?
Better still, just write (ArrayList. (range 6)). Or if the java code is well written, and only requires an Iterable, List, or Collection - anything less specific than ArrayList - you can simply return (range 6).
Use doseq instead of the lazy for. It has for-like bindings but it's meant for side-effects.
(defn make-an-array-list2 []
(let [alist (java.util.ArrayList.)]
(doseq [n (range 6)] (.add alist n)) alist))
;; [0 1 2 3 4 5]
Here is a more explicit answer for why the second example doesn't work. The for expression is lazy; in other words, it isn't evaluated unless its result are consumed by something. You throw away the result of the for expression because you only care about the side-effects, so it's never actually evaluated.
Here is an example of the same phenomenon:
(defn example[]
(for [n (range 6)]
(println "n=" n))
(println "done"))
(example)
;; done
;; nil
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