Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/clojure/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在Clojure中将可变方法映射到Java对象_Java_Clojure_Interop - Fatal编程技术网

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

在Clojure中将可变方法映射到Java对象,java,clojure,interop,Java,Clojure,Interop,使用Clojure,假设t代表一个Java对象,我有一个[t]的集合 如何将.setter映射到[ts]?我在使用map.setter%1%2 ts[VAL]时遇到问题。当我随后访问相关的getter时,我返回一个nil列表。听起来setter方法没有返回修改过的t对象。如果您编写了setter,您可以对其进行修改,使其生效,或者您只需保留原始ts,但还要确保使用它来挤出map的惰性: 如果让地图返回集合更方便,另一种方法是执行以下操作: (dorun (map #(do (.setter %1

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

如何将.setter映射到[ts]?我在使用map.setter%1%2 ts[VAL]时遇到问题。当我随后访问相关的getter时,我返回一个nil列表。

听起来setter方法没有返回修改过的t对象。如果您编写了setter,您可以对其进行修改,使其生效,或者您只需保留原始ts,但还要确保使用它来挤出map的惰性:

如果让地图返回集合更方便,另一种方法是执行以下操作:

(dorun (map #(do (.setter %1 %2) %1) ts [vals]))
听起来setter方法没有返回修改过的t对象。如果您编写了setter,您可以对其进行修改,使其生效,或者您只需保留原始ts,但还要确保使用它来挤出map的惰性:

如果让地图返回集合更方便,另一种方法是执行以下操作:

(dorun (map #(do (.setter %1 %2) %1) ts [vals]))
作为ArrayList Java类的一个示例。我创建了其中三个,然后将s1添加到第一个,s2添加到第二个,s3添加到第三个。这是我的二传手

然后我读取每一个的第一个值,我希望得到s1,s2,s3-所以在这个例子中这是一个getter

(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返回一个惰性序列,这意味着除非您尝试获取/使用它生成的值,否则它将不会进行计算-并且您通常不需要setter的返回值。这意味着您的setter将永远不会被调用

这就是为什么我使用了-它将采用一个惰性序列并实现它,这意味着在您的情况下每个元素都将被计算-每个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
它确实失败了,因为没有添加任何元素

或者,您可以使用一个变量,该变量返回一个向量,因此始终不懒惰:

(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))
正如@johnwiseman在评论中指出的,mapv可能是一个更糟糕的选择,因为并不总是清楚它是用来强制实现的,而doall则清楚而明显地说明了这一点

关于惰性序列的一句话:

A lazy seq is a seq whose members aren't computed until you try to access them.
了解更多关于lazy-seq的信息是件好事,因为它们是Clojure代码库中广泛使用的强大工具。他们带来的一个有点违反直觉的东西是创建无限序列的能力,即range创建一个由所有数字组成的无限序列,从0开始。因此,这样做完全合法:

(map #(* % %) (range))
它将创建一个由所有数字的平方组成的无限延迟序列

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

然后我读取每一个的第一个值,我希望得到s1,s2,s3-所以在这个例子中这是一个getter

(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返回一个惰性序列,这意味着除非您尝试获取/使用它生成的值,否则它将不会进行计算-并且您通常不需要setter的返回值。这意味着您的setter将永远不会被调用

这就是为什么我使用了-它将采用一个惰性序列并实现它,这意味着在您的情况下每个元素都将被计算-每个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
它确实失败了,因为没有添加任何元素

或者,您可以使用一个变量,该变量返回一个向量,因此始终不懒惰:

(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))
正如@johnwiseman在评论中指出的,mapv可能是一个更糟糕的选择,因为并不总是清楚它是用来强制实现的,而doall则清楚而明显地说明了这一点

关于惰性序列的一句话:

A lazy seq is a seq whose members aren't computed until you try to access them.
了解更多关于lazy-seq的信息是件好事,因为它们是Clojure代码库中广泛使用的强大工具。他们带来的一个有点违反直觉的东西是创建无限序列的能力,即range创建一个由所有数字组成的无限序列,从0开始。因此,这样做完全合法:

(map #(* % %) (range))

它将创建一个由所有数字的平方组成的无限延迟序列

我不建议仅仅为了避免懒惰而使用mapv,因为它模糊了程序员的意图。doall只有一个目的,如果我在代码中看到doall,我就能确切地知道它为什么在那里。@JohnWiseman-好的观点,我会重新安排答案,使其成为默认选择。在这种情况下,我会使用doseq而不是doall。鉴于OP正在对现有集合进行变异,
没有必要生成另一个被丢弃的中间集合。起初我以为是doseq,但存在VAL集合,我不确定如何最好地处理它们。doseq[[tV]映射向量ts vals]。setter tV似乎有点毫无意义。如果不访问操作的返回值,则dorun比doall更可取。在Clojure 1.7中,您可以使用run!而不是多伦地图。。。除了这种情况,因为可悲的是不像地图跑!不采用任意参数列表我不建议使用mapv,只是为了避免懒惰,因为它模糊了程序员的意图。doall只有一个目的,如果我在代码中看到doall,我就能确切地知道它为什么在那里。@JohnWiseman-好的观点,我会重新安排答案,使其成为默认选择。在这种情况下,我会使用doseq而不是doall。考虑到OP对集合进行了适当的变异,没有必要生成另一个被丢弃的中间集合。我起初以为是doseq,但存在VAL集合,我不确定如何最好地处理它们。doseq[[tV]映射向量ts vals]。setter tV似乎有点毫无意义。如果不访问操作的返回值,则dorun比doall更可取。在Clojure 1.7中,您可以使用run!而不是多伦地图。。。除了这种情况,因为可悲的是不像地图跑!不接受任意参数列表您可能还喜欢clojure.core/memfnI您可能还喜欢clojure.core/memfnI根据@noisesmith对另一个答案的评论将doall改为dorun。我根据@noisesmith对另一个答案的评论将doall改为dorun。