如何在Clojure中保存对象列表?

如何在Clojure中保存对象列表?,clojure,Clojure,我正在尝试使用java互操作来创建对象列表 我尝试了for和doseq,但他们都有问题 for是惰性的,我需要创建所有对象,因为它们在内部相互交互 (def master-object (MasterObject.)) (for [x [1 10 50 99]] (let [child (.createChildObject master-object)] (.setCoefficient child x) child)) doseq创建全部,但不返回列表 (doseq

我正在尝试使用java互操作来创建对象列表

我尝试了
for
doseq
,但他们都有问题

for
是惰性的,我需要创建所有对象,因为它们在内部相互交互

(def master-object (MasterObject.))

(for [x [1 10 50 99]]
  (let [child (.createChildObject master-object)]
    (.setCoefficient child x)
    child))
doseq
创建全部,但不返回列表

(doseq [x [1 10 50 99]]
  (let [child (.createChildObject master-object)]
    (.setCoefficient child x)
    child))
我正在考虑使用
循环
重现
,但我想知道这是否是一种更惯用的方法


谢谢

如果您需要创建所有对象,那么我认为返回一个向量而不是一个列表将是一种习惯做法,例如:

(vec (for [x (range 3)]
       x))
有几种不同的方法可以强制执行
for
的所有输出。以上就是其中之一
vec
只是
到[]
的缩写。因此,如果您确实需要一份清单,您可以:

(into '() (for [x (range 3)]
            x))
对于创建对象列表,
doseq
对您没有帮助,因为它只涉及“副作用”

实际上,您可以考虑使用
map
实现您想要实现的目标。制作一个单独的映射函数并映射到该函数上:

(defn make-child [x]
  (let [child (.createChildObject master-object)]
      (.setCoefficient child x)
      child))

(map make-child [1 10 50 99])

实现惰性序列的神奇词语是。如果将其环绕在的
上,您将获得想要的效果:

(doall
  (for [x [1 10 50 99]]
    (let [child (.createChildObject master-object)]
      (.setCoefficient child x)
      child)))

=>
(#object[interop.core.ChildObject 0x326037f1 "interop.core.ChildObject@326037f1"]
 #object[interop.core.ChildObject 0x759b711 "interop.core.ChildObject@759b711"]
 #object[interop.core.ChildObject 0x2bc06dcb "interop.core.ChildObject@2bc06dcb"]
 #object[interop.core.ChildObject 0x4a37a35a "interop.core.ChildObject@4a37a35a"])
请注意,返回的对象是一个
LazySeq
,而不是一个列表。而REPL无论如何都会迫使它实现

如果
setCoefficient
返回Java
this
,则可以将上述内容缩写为

(doall
  (for [x [1 10 50 99]]
    (.. master-object
        (createChildObject)
        (setCoefficient x))))

你的代码结构让我担心。您正在实现
主对象
子对象
之间一半的关联-子对象知道其主对象;但不是另一半——主人不认识自己的孩子。我们看不到您对生成的子集合执行任何操作。如果是这样的话,就没有任何东西会提到它们,它们是垃圾,任何时候都会被处理掉

我认为
MasterObject
应该保留其子对象的集合,在
createChildObject
中创建
ChildObject
时添加到该集合中。这样,您就不必保留已创建子项的集合,而且对于
,首选
doseq
。我完全是在Clojure interop中完成的,如下所示:

(ns interop.core)

(definterface ChildInterface
  (setCoefficient [x]))

(definterface MasterInterface
  (createChildObject [])
  (getChildren []))

(deftype ChildObject [master ^:unsynchronized-mutable coefficient]
  Object
  (toString [this]
    (str "Child " coefficient))
  ChildInterface
  (setCoefficient [this x]
    (set! coefficient x)
    this))

(deftype MasterObject [^:unsynchronized-mutable children]
  Object
  (toString [this]
    (str "Master children: " (.seq children)))
  MasterInterface
  (createChildObject [this]
    (let [child (ChildObject. this nil)]
      (set! children (conj children child))
      child))
  (getChildren [this]
    children))

(def master-object (MasterObject. []))

(doseq [x [1 10 50 99]]
  (.. master-object
      (createChildObject)
      (setCoefficient x)))
这仍然很难看,因为我还没有弄清楚如何抑制Java对象的默认呈现:

master-object
=>
#object[interop.core.MasterObject
        0x3f7683a
        "Master children: (#object[interop.core.ChildObject 0xb1cf4bb \"Child 1\"] #object[interop.core.ChildObject 0x16b56f70 \"Child 10\"] #object[interop.core.ChildObject 0x5dadc8ab \"Child 50\"] #object[interop.core.ChildObject 0x6f22f049 \"Child 99\"])"]

我为孩子们使用了Clojure向量。在这种情况下,Java集合也可以

谢谢你的回答。我发现非常令人困惑的是找到了实现我的seq的函数。例如,将
转换为
。关于Java部件的结构,您是对的,它是一个第三方库,并且它确实保留了它的子项的引用,但是API希望我知道我所做的子项,我不能要求所有的子项。