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?
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With