将可变方法映射到Clojure中的Java对象

时间:2015-07-13 17:26:48

标签: java clojure interop

使用Clojure,假设t代表一个Java对象,我有一个[ts]的集合。

如何将.setter映射到[ts]?我在使用(map #(.setter %1 %2) ts [vals])时遇到问题。当我之后访问相关的getter时,我会返回nil s的列表。

2 个答案:

答案 0 :(得分:2)

听起来setter方法没有返回修改后的t对象。如果你写了setter,你可以修改它,或者你只需​​要保留原来的ts(但也要确保使用dorun来挤出懒惰map):

(let [ts ...]
  (dorun (map #(.setter %1 %2) ts [vals]))
  (println "Modified ts:" ts))

另一种选择,如果让map返回集合会更方便,就是这样做:

(dorun (map #(do (.setter %1 %2) %1) ts [vals]))

答案 1 :(得分:2)

作为ArrayList Java类的示例。我创建了其中的三个,然后我添加" s1"到第一个," s2"到第二个" s3"到第三个。这是我的" setter"。

然后我读了每个的第一个值,我希望得到" s1"," s2"," s3" - 这个例子中的吸气剂。

(let [ts [(java.util.ArrayList. 1)
          (java.util.ArrayList. 1)
          (java.util.ArrayList. 1)]]
  ; Add one element to each of the ArrayList's
  (doall (map #(.add %1 %2) ts ["s1" "s2" "s3"]))

  ; Verify that elements are indeed added.
  (doall (map #(.get %1 0) ts)))

此示例按预期工作 - 后者mapv返回("s1" "s2" "s3")

为什么类似的方法对你不起作用?好吧,我强烈怀疑是因为你使用了map来返回一个懒惰的序列。

map返回一个惰性序列,这意味着除非您尝试获取/使用由它生成的值,否则它不会进行评估 - 并且您通常不需要来自setter的返回值。这意味着永远不会调用你的setter。

这就是我使用doall的原因 - 它将采用一个懒惰的序列并实现它,这意味着每个元素都将被计算(在你的情况下 - 每个setter都会被调用)。

我的例子,当我在设置元素时仅使用map而不是doall时,会失败:

(let [ts [(java.util.ArrayList. 1)
          (java.util.ArrayList. 1)
          (java.util.ArrayList. 1)]]
  ; Use a lazy map here - without doall
  (map #(.add %1 %2) ts ["s1" "s2" "s3"])
  (doall (map #(.get %1 0) ts)))

; java.lang.IndexOutOfBoundsException: Index: 0, Size: 0

确实失败了,因为没有添加任何元素。

或者,您可以使用返回向量的mapv变体,因此始终不是懒惰的:

(let [ts [(java.util.ArrayList. 1)
          (java.util.ArrayList. 1)
          (java.util.ArrayList. 1)]]
  ; Use a lazy map, but realize sequence using doall
  (doall (map #(.add %1 %2) ts ["s1" "s2" "s3"]))
  (mapv #(.get %1 0) ts))

正如@John Wiseman在评论中指出的那样,mapv可能是一个更糟糕的选择,因为它并不总是很清楚,它曾用于强迫实现,而{{1}明确而明显。

关于懒惰序列的一句话:

doall

(source)

了解懒惰seqs是一件好事,因为它们是Clojure代码库中使用的强大工具。他们带来的一个反直觉的东西是创造无限序列的能力,即(范围)创建从0开始的所有数字的无限序列。所以它完全合法:

A lazy seq is a seq whose members aren't computed until you try to access them.

它将创建所有数字的无限懒惰的正方形序列!