两个clojure地图引用作为彼此的元素

Fin*_*inn 3 clojure circular-reference refs

我在refs中有两个映射,并希望在一个事务中将它们相互关联.

我的功能看起来像这样:

(defn assoc-two
  [one two]
  (let [newone (assoc @one :two two)
        newtwo (assoc @two :one one)]
    (ref-set one newone)
    (ref-set two newtwo)))
Run Code Online (Sandbox Code Playgroud)

现在我这样打电话assoc-two:

(dosync (assoc-two (ref {}) (ref {})))
Run Code Online (Sandbox Code Playgroud)

我现在得到和StackOverflowError.

我也试过这个:

(defn alter-two
  [one two]
  (alter one assoc :two two)
  (alter two assoc :one one))
Run Code Online (Sandbox Code Playgroud)

有没有这样做的方式one有一个条目参考two,反之亦然,仍然在一个交易中?

A. *_*ebb 6

在尝试打印其中一个循环引用之前,不会发生堆栈溢出,例如在REPL处.

so.core=> (def a (ref {}))
#'so.core/a
so.core=> (def b (ref {}))
#'so.core/b
so.core=> (do (dosync (alter-two a b)) :success)
:success
so.core=> (= b (:two @a))
true
so.core=> (= a (:one @b))
true

显然打印这样的循环引用对象会有问题,但请参阅最近的问题和答案,禁用默认打印引用类型的内容

(remove-method print-method clojure.lang.IDeref)

(dosync (alter-two (ref {}) (ref {})))
;=> {:one #<Ref clojure.lang.Ref@7f1f91ac>} 
;   (prints the second ref without attempting to print its circular contents)
Run Code Online (Sandbox Code Playgroud)