It seems that the code is correct, but caused a stackoverflow due to trying to evaluate the list. Since the list has cyclic references, (previous and next), it isn't possible to 'evaluate' it, hence causing the error.
Clojure refs odd behaviour
-
30-05-2022 - |
Frage
I feel like I'm missing something about the use of refs, something under the hood that isn't happening like I think it is. I'm making a thread-safe double linkedlist where the list is a hash containing refs to head and tail. A node of the list is represented by a hash containing previous, next and value.
(defn insert
[list elem]
(dosync
(let [head @(:head list)]
(if (nil? head)
(do (ref-set (:head list) elem)
(ref-set (:tail list) elem))
(do
(ref-set (:head list) elem)
(ref-set (:next elem) head);;fails!
(ref-set (:prev head) elem))))));;fails!
This gives me a StackOverflow error. To be exact:
StackOverflowError java.util.regex.Pattern$Curly.match
It feels like I miss something in how refs work in Clojure, can anybody tell me what's wrong?
EDIT: Here is a link to the full "code". https://www.refheap.com/6544630b38b33b9d25d999829 it fails on the last line, in the else clause of the insert function, when the head is not null anymore.
(def f (create-doubly-linked-list))
(def n (create-node 2))
(insert f n)
(def m (create-node 3))
(insert (f m);;error!
Note that the error manifests when I try to access the list, or ie when I evaluate f in the repl, or when I execute the last line in the REPL.
UPDATE: Following code works, but accessing the list causes problems as well as printing it.
(def f (create-doubly-linked-list))
(def n (create-node 2))
(insert f n)
(insert f (create-node 5))
(insert f (create-node 1))
(def m (create-node 3))
(insert f m)
(is (= @(:value @(:tail f)) 2))
(is (= @(:value @(:head f)) 3))
Lösung