如何在Clojure中创建一个ArrayList

7
我需要创建并填充一个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))
;;; ==> []

或者,有没有其他建议代替上述方法?
3个回答

17
更好的做法是直接写 (ArrayList. (range 6))。 如果Java代码已经写得很好,并且只需要可迭代对象、列表或集合 - 任何比ArrayList不具体的类型 - 那么你可以简单地返回(range 6)

真棒!简单就是最高的复杂! - Chiron

6

使用doseq替代懒惰的for。它具有类似于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]

4
这里是关于为什么第二个例子不起作用的更明确的答案。for表达式是惰性求值的,也就是说,除非它的结果被某些东西消耗掉,否则它不会被评估。您丢弃了for表达式的结果,因为您只关心其副作用,因此它实际上从未被评估。下面是一个相同现象的例子:
(defn example[] 
   (for [n (range 6)] 
      (println "n=" n))
   (println "done"))
(example)
;; done
;; nil

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接