如何表示两个记录/映射之间的父子关系?

问题描述 投票:0回答:1

我正在尝试在Clojure / Script中表示gui元素。问题在于元素是嵌套的,需要彼此通信。我本以为可以互相引用,但是像我天真地想的那样,似乎我不能只是互相引用。

我尝试过的代码

(defrecord Element [position size parent children state type value])
(def parent (atom (Element. ...)))
(def child  (atom (Element. ...)))
(assoc @parent :child child)
(assoc @child :parent parent)

这不起作用。

Clojure中针对此类问题的惯用解决方案是什么?


更新:相互引用似乎不起作用:

(defrecord Element [position size parent children state type value])

(def parent (atom (Element. {:x 0 :y 0} {:width 1600 :height 900} nil nil :collapsed :container nil)))

(def child (atom (Element. {:x 5 :y 5} {:width 100 :height 100} nil nil :collapsed :container nil)))

(swap! parent assoc :child child)
(swap! child assoc :parent parent)

#object[InternalError InternalError: too much recursion]
   cljs.core.PersistentArrayMap.prototype.cljs$core$ILookup$_lookup$arity$2 (jar
:file:/C:/Users/user/.m2/repository/org/clojure/clojurescript/1.10.520/clojuresc
ript-1.10.520.jar!/cljs/core.cljs:6811:10)

也许在Clojure中您不互相引用?

clojure clojurescript
1个回答
1
投票

您将assoc赋予孩子的父母,但随后扔掉了新的Element。您需要使用reset!swap!在原子中设置值:

(swap! parent assoc :child child)  ; Equivalent to (swap! parent #(assoc % :child child))
(swap! child assoc :parent parent)

[swap!swap!相似,但是它替换了update中保存的值。


[另外请注意,您给字段指定了update,但是在您的示例中,您使用的是atom。虽然children建议有多个孩子,所以我将其更改为矢量而不是:child,然后是children。我还要创建一个nil助手:

conj

为了解决您遇到的错误,它在Clojure中对我来说运行正常。

如果在上面的代码运行后打印new-element(defrecord Element [position size parent children state type value]) (defn new-element [position size] (->Element position size nil [] :collapsed :container nil)) (def parent (atom (new-element {:x 0 :y 0} {:width 1600 :height 900}))) (def child (atom (new-element {:x 5 :y 5} {:width 100 :height 100}))) (swap! parent update :children conj child) (swap! child assoc :parent parent) ,则会得到无限输出,因为要打印父级,您需要打印子级,而要打印子级,则需要打印父级...它仍然对我有用。

请确保不会发生此错误,因为您正尝试在REPL中打印出该结构。

这也可能是Clojurescript的局限性。不幸的是,由于我不熟悉Cljs,我无法回答。

如果最终没有帮助,我将删除答案。


我还将注意,嵌套原子不是一个好主意。 parent实际上是可变的容器,用于保存不可变的对象。拥有一个ID系统,让每个父母/孩子为其孩子/父母持有一个数字ID,可能会更清洁。然后,整个程序只有一个原子。原子可以保存ID-> element的映射以便于查找。

© www.soinside.com 2019 - 2024. All rights reserved.