2

我觉得我错过了一些关于使用 refs 的东西,一些没有像我想的那样发生的事情。我正在制作一个线程安全的双链表,其中列表是一个包含对头和尾的引用的哈希。列表的节点由包含前一个、下一个和值的散列表示。

(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!

这给了我一个 StackOverflow 错误。准确地说:

StackOverflowError java.util.regex.Pattern$Curly.match

感觉就像我错过了 refs 在 Clojure 中的工作方式,任何人都可以告诉我有什么问题吗?


编辑:这是完整“代码”的链接。 https://www.refheap.com/6544630b38b33b9d25d999829 它在最后一行失败,在插入函数的 else 子句中,当头部不再为空时。

(def f (create-doubly-linked-list))
(def n (create-node 2))
(insert f n)
(def m (create-node 3))
(insert (f m);;error!

请注意,当我尝试访问列表时,或者当我在 repl 中评估f时,或者当我执行 REPL 中的最后一行时,就会出现错误。


更新:以下代码有效,但访问列表会导致问题以及打印它。

(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))
4

1 回答 1

0

似乎代码是正确的,但由于试图评估列表而导致堆栈溢出。由于列表具有循环引用(上一个和下一个),因此无法“评估”它,从而导致错误。

于 2013-06-04T18:12:21.937 回答