假设我们正在使用面向对象的语言,并且有两个类 X 和 Y,并且这些类之间存在双向关系。
所以 X 的一个实例可以指向 Y 的一个实例,反之亦然。
在 Clojure 中,类通常转换为映射,因此我们可以:
{:type :x :name "instance of X"}
{:type :y :name "instance of Y"}
我们如何表示这些“对象”之间的双向关系,而不使用“外键”之类的东西?或者这通常是直接委托给数据库的东西?
在 Clojure 中看到与面向对象语言中的分层对象树相对应的深度嵌套映射是很常见的,例如
{:type :x
:name "instance of X"
:y {:type :y
:name "instance of Y"}}
事实上,这很常见,它提供了诸如、和之类的clojure.core
核心功能,以方便使用此类结构。get-in
assoc-in
update-in
当然,当被建模的对象之间存在自然的层次结构或所有权关系时,这种方法效果最好。在循环引用的情况下,这种结构会崩溃(假设您坚持使用持久数据结构)——要了解原因,请尝试构建一个包含自身作为值的 Clojure 映射。
我通常看到处理这种情况的方式是使用以下方法引入一个间接层atom
:
(def x {:type :x, :name "x instance", :y (atom nil)})
(def y {:type :y, :name "y instance", :x (atom nil)})
(set! *print-level* 3) ;; do this in the REPL to avoid stack overflow
;; when printing the results of the following calls
(reset! (:y x) y)
(reset! (:x y) x)