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

时间:2017-06-24 02:43:29

标签: clojure

我正在尝试使用java interop来创建对象列表。

我尝试了fordoseq,但他们都遇到了问题。

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))

我在考虑使用looprecur,但是想知道是否可以采用更惯用的方式。

由于

2 个答案:

答案 0 :(得分:2)

如果你需要创建所有对象,那么我认为返回向量而不是列表是惯用的,例如:

(vec (for [x (range 3)]
       x))

有几种不同的方法可以强制for的所有输出。以上就是其中之一。 vec只是into []的缩写。因此,如果您确实需要一个已实现的列表,则可以改为:

(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])

答案 1 :(得分:0)

实现延迟序列的神奇词是doall。如果你将它包裹在var request = $.ajax({ type: 'GET', url: url, dataType: 'json', xhrFields: { withCredentials: true }}); 周围,你将得到你想要的效果:

for

请注意,返回的对象是(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"]) ,而不是列表。无论如何,REPL迫使其实现。

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

this

你的代码结构让我很担心。你正在实现(doall (for [x [1 10 50 99]] (.. master-object (createChildObject) (setCoefficient x)))) MasterObject之间关联的一半 - 一个孩子知道它的主人;但不是另一半 - 主人不知道它的孩子。我们没有看到您对生成的子集合执行任何操作。如果是这样的话,没有任何东西可以引用它们,并且它们是垃圾,随时都会被处理掉。

我认为ChildObject应保留其子集合,并在MasterObject中创建ChildObject时添加。然后,您无需保留已创建子项的集合,createChildObject将优先于doseq。我完全在Clojure interop中完成了如下操作:

for

这仍然非常难看,因为我还没有弄清楚如何抑制Java对象的默认呈现:

(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)))

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