【问题标题】:Clojure refs odd behaviourClojure 引用奇怪的行为
【发布时间】: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


【解决方案1】:

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

【讨论】:

    猜你喜欢
    • 2016-12-27
    • 2013-06-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-07-12
    • 1970-01-01
    • 2021-12-15
    相关资源
    最近更新 更多