跟踪Clojure程序中的StackOverflow,包含SSCCE

跟踪Clojure程序中的StackOverflow,包含SSCCE,clojure,stack-overflow,list-comprehension,Clojure,Stack Overflow,List Comprehension,我很难跟踪的clojure实现所产生的stackoverflow错误 下面是我对算法本身的实现,这里是一个指向SSCCE的链接,概述了这个问题 我必须假设问题显然存在于我的两个引导条件之一之内,因为函数算法是递归的 虽然这假设我正在正确地构建列表xrp。从注释输出的语句(cliques总是以空列表形式打印)判断,我假设我的列表理解可能也是问题所在 同样,我可以看到的另一个问题是,我没有在BK Call函数(在SSCCEE中)中正确调用算法 我的总体问题是什么导致了这一点?虽然这有点过于开放,但另

我很难跟踪的clojure实现所产生的stackoverflow错误

下面是我对算法本身的实现,这里是一个指向SSCCE的链接,概述了这个问题

我必须假设问题显然存在于我的两个引导条件之一之内,因为函数算法是递归的

虽然这假设我正在正确地构建列表
xrp
。从注释输出的语句(cliques总是以空列表形式打印)判断,我假设我的列表理解可能也是问题所在

同样,我可以看到的另一个问题是,我没有在
BK Call
函数(在SSCCEE中)中正确调用算法

我的总体问题是什么导致了这一点?虽然这有点过于开放,但另一个可能让我找到答案的问题是,我如何在第一行使用print语句

当print语句未注释时,它将生成输出

R:clojure.lang.LazySeq@2044e0b9 P:clojure.lang.LazySeq@7f9700a5 X:clojure.lang.LazySeq@1 Clq:clojure.lang.PersistentList$EmptyList@1
我假设,如果我能看到
xrp
在每次调用中都出现了错误,我可能就能看到算法出了什么问题

谁能给我指出正确的方向吗

编辑:来自SSCCE的
neighV
功能

(defn neighV [graph nodenum]
  (let [ret-list (for [i (range (count graph)) :when (contains? (graph i) nodenum)] i)]
    ret-list))
EDIT2:Noisesmith的回答让我更接近解决方案,对我来说很有意义。我将所有的
concat
包装在
doall
中。再次尝试调用该函数后,我得到了“不能长时间转换为Seq”错误,我认为这些错误源于试图
concat
将cnt
循环到函数中的列表上

fptests.core> (BK-Call (sanity1))
IllegalArgumentException Don't know how to create ISeq from: java.lang.Long  clojure.lang.RT.seqFrom (RT.java:505)
fptests.core> (concat 1 '(2 3))
IllegalArgumentException Don't know how to create ISeq from: java.lang.Long  clojure.lang.RT.seqFrom (RT.java:505)
因此,我随后将每个
循环cnt
包装在一个
'()
中,以便在它成为
concat之前将其转换为一个列表

fptests.core> (concat '(1) '(2 3))
(1 2 3)
在我做了所有这些更改之后,我回到了堆栈溢出状态。这是新的
Bron Kerbosch
函数,包含所有编辑。我想我现在的问题和以前一样

虽然新的是,但是我是否正确地实现了我应该进行的更改,
'()
的使用对于解决在实现noisesmith的更改后出现的问题是否有意义

(defn Bron-Kerbosch1 [r p x graph cliques]
  (cond (and (empty? p) (empty? x)) (doall (concat cliques r))
        :else
        (let [neigh (neighV graph (dec (count p)))]
          (loop [loop-clq '(cliques)
                 loop-cnt (dec (count p))
                 loop-p '(p)
                 loop-x '(x)]
            (cond (= -1 loop-cnt) loop-clq
                  :else
                  (recur (doall (concat loop-clq 
                                        (Bron-Kerbosch1 (doall (concat r '(loop-cnt))) 
                                                       (doall (concat p neigh)) 
                                                       (filter (set x) neigh) 
                                                       graph cliques)))
                         (dec loop-cnt)
                         (filter (set p) '(loop-cnt))
                         (doall (concat x '(loop-cnt)))))))))
EDIT3:在耐心地等待我的
prn
语句停止后(不知道为什么我会在知道是SO的情况下把它们放进去),我发现大多数(如果不是所有的话)语句都是按照

"R:" (loop-cnt loop-cnt loop-cnt loop-cnt loop-cnt loop-cnt loop-cnt ...)
"P:" (range (count graph) 0 2 3) " X:" () " Clq:" ()
在检查了一些之后,我意识到我没有正确地递归调用函数。我一直在将项合并到
p
,而不是删除它们。这导致
p
不断增长。这很可能是我的堆栈溢出的原因。尽管仍然存在一些问题。我仍然在创建堆栈溢出又一次

一旦我解决了继续并集到p的问题,我的问题是当我
concat
loop cnt
时,它不是一个值,而是一个变量名
loop cnt
。我怀疑我的堆栈溢出现在是由于我的引导条件没有满足,因为如果
loop cnt,它就不能满足未计算为数字


因此,我认为我现在的问题在于
concat
将cnt
作为一个数字而不是一个变量循环到一个列表中。

concat
是懒惰的。在
concat
之上构建
concat
的递归调用,在没有意识到之前任何一层懒惰的情况下,每一层都会增加nee调用堆栈的大小为了实现懒惰的顺序

这种连接需要延迟吗?如果不需要,请将对
concat
的调用包装在对
doall
的调用中。这将使连接变得急切,从而减少实现最终结果所需的调用堆栈的大小,从而消除StackOverflower错误


另外,打印惰性seq并查看内容的正确方法是
prn
,您可以使用
pr str
获取值的形式,如果需要,
pr
prn
将用作字符串。

我认为您误用了引用列表

例如,在
(defn Bron-Kerbosch1[…])
中,
”(小团体)
的计算结果是包含符号
小团体的列表,而不是包含参数
小团体作为其一个元素的列表。您需要
(小团体)


类似的情况比比皆是。

当堆栈溢出发生时,输出是什么样子的?您可能想在Clojure中查看BK算法的一个更为惯用的版本:neighV
函数是什么样子?@BobJarvis我在问题的编辑中添加了
neighV
。如果您需要查看这些seq的内容结果您可以使用
doall
来实现序列,例如
(println(str“R:”(doall R)“P:”(doall P)“X:”(doall X)“Clq:“clques))
pr str
是以列表形式获取惰性seq字符串的正确方法。或者,使用
prn
而不是
println
将打印每个参数的可读版本(如果可用)。谢谢,我将尝试此方法。我想现在会出现一些混乱。如果我计算
(concat'(1)-(2 3))
在REPL中返回
(1 2 3)
。为什么我没有收到结果是一个惰性序列而不是正在计算的消息?//所以它没有停止的原因是它无法执行任何引导条件,因为惰性序列没有被计算?我再次更新了这个问题,我设法回到了堆栈溢出。我在您的建议中添加了DDE,并在尝试将我的循环计数器(表示节点)添加到列表中时出现另一个错误
"R:" (loop-cnt loop-cnt loop-cnt loop-cnt loop-cnt loop-cnt loop-cnt ...)
"P:" (range (count graph) 0 2 3) " X:" () " Clq:" ()