两个clojure映射引用互为元素

两个clojure映射引用互为元素,clojure,circular-reference,refs,Clojure,Circular Reference,Refs,我在REF中有两个映射,希望在一个事务中将它们彼此关联 我的函数如下所示: (defn assoc-two [one two] (let [newone (assoc @one :two two) newtwo (assoc @two :one one)] (ref-set one newone) (ref-set two newtwo))) (dosync (assoc-two (ref {}) (ref {}))) 现在我像这样呼叫assoctwo

我在REF中有两个映射,希望在一个事务中将它们彼此关联

我的函数如下所示:

(defn assoc-two
  [one two]
  (let [newone (assoc @one :two two)
        newtwo (assoc @two :one one)]
    (ref-set one newone)
    (ref-set two newtwo)))
(dosync (assoc-two (ref {}) (ref {})))
现在我像这样呼叫
assoctwo

(defn assoc-two
  [one two]
  (let [newone (assoc @one :two two)
        newtwo (assoc @two :one one)]
    (ref-set one newone)
    (ref-set two newtwo)))
(dosync (assoc-two (ref {}) (ref {})))
在这一点上,我得到了和StackOverflower错误

我也试过:

(defn alter-two
  [one two]
  (alter one assoc :two two)
  (alter two assoc :one one))

是否可以这样做,即
one
有一个引用
two的条目,反之亦然,并且仍然在一个事务中?

堆栈溢出不会发生,直到您尝试打印其中一个循环引用,例如在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 so.core=>(defa(ref{})) #“那么,core/a so.core=>(def b(ref{})) #'so.core/b so.core=>(do(dosync(altertwoab)):success) :成功 so.core=>(=b(:two@a)) 真的 so.core=>(=a(:one@b)) 真的 显然,像这样打印循环引用的对象会有问题,但请参阅关于禁用引用类型内容的默认打印

(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)
(删除方法打印方法clojure.lang.IDeref)
(dosync(altertwo(ref{})(ref{})))
;=> {:一#}
;   (打印第二个ref,而不尝试打印其循环内容)

答案可以在下面的几篇文章中找到,这只是试图打印递归结构的REPL。 您必须删除打印方法:

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

或者添加一个print方法来处理您的特定案例,这个方法必须比常见的
clojure.lang.IDeref

更具体。哦,我可能已经猜到了。非常感谢。