我需要在clojure中创建并填充ArrayList并将其传递给Java API。 有人可以帮助解释为什么以下两种方法存在差异(以及为什么其中一种方法不起作用)。
;;; 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))
;;; ==> []
或者,是否有任何建议代替上述方法?
答案 0 :(得分:16)
更好的是,只需写(ArrayList. (range 6))
即可。或者,如果java代码编写得很好,并且只需要Iterable,List或Collection - 任何不如ArrayList特定的东西 - 你只需返回(range 6)
。
答案 1 :(得分:4)
使用doseq
代替懒惰的for
。它有类似的绑定,但它的意思是副作用。
(defn make-an-array-list2 []
(let [alist (java.util.ArrayList.)]
(doseq [n (range 6)] (.add alist n)) alist))
;; [0 1 2 3 4 5]
答案 2 :(得分:3)
这是一个更明确的答案,为什么第二个例子不起作用。 for
表达式是懒惰的;换句话说,除非其结果被某些东西消耗,否则不会对其进行评估。你丢弃了for
表达式的结果,因为你只关心副作用,因此它实际上从未被评估过。
以下是同一现象的一个例子:
(defn example[]
(for [n (range 6)]
(println "n=" n))
(println "done"))
(example)
;; done
;; nil