【发布时间】:2013-06-03 22:23:06
【问题描述】:
我觉得我错过了一些关于使用 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
感觉好像我错过了 Clojure 中 refs 的工作方式,谁能告诉我有什么问题?
编辑:这是完整“代码”的链接。 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))
【问题讨论】:
-
鉴于您引用的消息,我认为实际错误可能与 Refs 无关;您必须包含更多上下文(最重要的是导致问题显现的实际代码段,而不是单独定义
insert函数)。除此之外,我不确定使用 Refs 来实现链表是否是一个好主意,但如果我要尝试这样做,我会使用 maps-in-Ref 而不是 Refs-in-map。 -
感谢您的评论,我编辑了问题并添加了其他信息以及指向 refheap 上源代码的链接。
标签: clojure ref stack-overflow