请在2024年Clojure状态调查中分享您的想法!

欢迎!请参阅关于页面以了解更多关于它如何工作的信息。

0
core.logic

这可能与core.logic如何打印向量结构有关

以下是重现问题的最小示例

(ns testclj.logic
(:require (link: clojure.core.logic :as l)))

(def data (link: [[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[:a)]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]])

(time (l/run* (link: q) (l/== q data)))

2 个答案

0

由:troydm

我认为问题与以下代码片段有关

`
(defn walk* [s v]
(let [v (walk s v)]

(walk-term v
  (fn [x]
    (let [x (walk s x)]
     (if (tree-term? x)
       (walk* s x)
       x))))))

`

另一方面,它调用

`
clojure.lang.IPersistentVector
(walk-term [v f]

(with-meta
  (loop [v v r (transient [])]
    (if (seq v)
      (recur (next v) (conj! r (walk-term (f (first v)) f)))
      (persistent! r)))
  (meta v)))

`

这个函数递归地对向量中的所有元素调用walk-term。
随后,它对向量中的每个元素再次调用walk-term,这又导致对之前已访问过的向量元素的 walk* 调用,进而再次在向量的元素上调用walk-term,并继续向下遍历,直到访问整个结构多次。
这总体上导致多次访问子节点

问题在于walk函数的部分,其中递归调用walk来对之前已被walk-term函数调用本身遍历过的向量元素进行遍历

我认为这部分的设计有一个非常大的问题,我不确定在这里提什么建议,但我认为我们需要将walk-term和walk*合并为一个函数,该函数将一次遍历整个数据结构,有什么建议吗?

`
(如果(tree-term? x)

       (walk* s x)
       x)

`

我认为这部分的设计有一个很大的问题,我不确定在这里提什么建议,但我认为我们需要将walk-term和walk*合并为单个函数,以便一次性遍历整个数据结构,有什么建议吗?

可能的解决方案如下代码,但我不确定它是否是正确的解决方案

`
(defn walk* [s v]
(let [v (walk s v)]

(walk-term v
    #(walk s %))))

`

0
参考:https://clojure.atlassian.net/browse/LOGIC-177(由 alex+import 报告)
...