Clojure - 重置!原子导致堆栈溢出

发布于 2024-11-02 22:57:39 字数 1660 浏览 0 评论 0原文

我正在学习 clojure,只是在玩原子和引用。这是一个简单的树实现,但在执行 add-child 方法时会导致堆栈溢出:

(ns mytree)

(defprotocol PNode
  (add-child [this parent] "add 'this' node to the parent"))

(defrecord Node [id parent name children]
  PNode
  (add-child [this p]
     (println "adding this to children of parent")       
     (dosync
      (alter (:children p) conj this))

     ;following causes a stack overflow -why?
;        (println "reseting parent of this")
;        (reset! parent p)

     ))

(defn create-node [id name]
  (Node. id (atom nil) name (ref ())))

这是来自 REPL 的示例会话:

>mytree> (def root (create-node 1 "CEO"))
>#'mytree/root
>mytree> (def child (create-node 2 "VP1"))
>#'mytree/child
>mytree> (add-child child root)

>adding this to children of parent

>(#:mytree.Node{:id 2, :parent #<Atom@4dffa9d: nil>, :name "VP1", :children #<Ref@cbe5beb:      ()>})

>mytree> root
>#:mytree.Node{:id 1, :parent #<Atom@44896098: nil>, :name "CEO", :children #<Ref@2a75733a: >(#:mytree.Node{:id 2, :parent #<Atom@4dffa9d: nil>, :name "VP1", :children #<Ref@cbe5beb: ()>})>}
>mytree> (def child2 (create-node 3 "VP2"))
>#'mytree/child2

resetting parent to child2 works
>mytree> (reset! (:parent child) child2)
>#:mytree.Node{:id 3, :parent #<Atom@43c32b82: nil>, :name "VP2", :children #<Ref@425d868f: ()>}

but resetting parent to root causes stack overflow - why??
>mytree> (reset! (:parent child) root)
>; Evaluation aborted.

正如您在上面所看到的,将 child 的parent 重置为 child2 是有效的,但将其重置为根本原因堆栈溢出。你能帮我理解为什么吗?

I am learning clojure and just playing with atoms and refs. Here is a simple tree implementation, but it is causing a stack overflow when executing the add-child method:

(ns mytree)

(defprotocol PNode
  (add-child [this parent] "add 'this' node to the parent"))

(defrecord Node [id parent name children]
  PNode
  (add-child [this p]
     (println "adding this to children of parent")       
     (dosync
      (alter (:children p) conj this))

     ;following causes a stack overflow -why?
;        (println "reseting parent of this")
;        (reset! parent p)

     ))

(defn create-node [id name]
  (Node. id (atom nil) name (ref ())))

Here is a sample session from REPL:

>mytree> (def root (create-node 1 "CEO"))
>#'mytree/root
>mytree> (def child (create-node 2 "VP1"))
>#'mytree/child
>mytree> (add-child child root)

>adding this to children of parent

>(#:mytree.Node{:id 2, :parent #<Atom@4dffa9d: nil>, :name "VP1", :children #<Ref@cbe5beb:      ()>})

>mytree> root
>#:mytree.Node{:id 1, :parent #<Atom@44896098: nil>, :name "CEO", :children #<Ref@2a75733a: >(#:mytree.Node{:id 2, :parent #<Atom@4dffa9d: nil>, :name "VP1", :children #<Ref@cbe5beb: ()>})>}
>mytree> (def child2 (create-node 3 "VP2"))
>#'mytree/child2

resetting parent to child2 works
>mytree> (reset! (:parent child) child2)
>#:mytree.Node{:id 3, :parent #<Atom@43c32b82: nil>, :name "VP2", :children #<Ref@425d868f: ()>}

but resetting parent to root causes stack overflow - why??
>mytree> (reset! (:parent child) root)
>; Evaluation aborted.

As you can see above, reseting parent of child to child2 works, but resetting it to root causes a stack overflow. Can you help me understand why?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

地狱即天堂 2024-11-09 22:57:39

它实际上不是 reset! 而是 REPL 尝试打印(无限)嵌套值。

试试这个:

(set! *print-level* 10)

这将限制分层对象的递归打印。

It's not actually the reset! but the REPL trying to print the (infinitely) nested values.

Try this:

(set! *print-level* 10)

That will limit the recursive printing of hierarchical objects.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文