How to make an ArrayList in Clojure

I need to create and populate an ArrayList in clojure and pass it to the Java API. Can someone help explain why there is a difference in the two approaches (and why one of them does not 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 instead of the above approach?

+4
source share
3 answers

Use doseqinstead of lazy for. It has for-like bindings, but it was intended 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]
+4
source

Better yet, just write (ArrayList. (range 6)). Or, if the Java code is well written and requires only Iterable, List or Collection - something less than an ArrayList, you can simply return (range 6).

+15

Here is a more explicit answer why the second example does not work. The expression foris lazy; in other words, it is not evaluated if its result is not consumed by something. You throw away the result of the expression forbecause you only care about side effects, so it has never been evaluated.

Here is an example of the same phenomenon:

(defn example[] 
   (for [n (range 6)] 
      (println "n=" n))
   (println "done"))
(example)
;; done
;; nil
+3
source

All Articles