我一直在和Clojure一起玩,我设法打破了筹码.在这段代码中,我只使用recur进行递归.我正在进行大量的连接(请注意下面的跟踪调用concat).我试图在所有连接列表上执行操作,因为这些是懒惰的,我希望它们在我进行时进行评估.我仍然得到堆栈溢出.这是跟踪.我认为这可能是一个普遍的问题,而且有更多经验黑客攻击的人可以指出我正确的方向.
这是造成问题的代码段.
(defn move-split [[xs ys]] (doall (concat (list (concat xs (list (first ys)))) (list (next ys)))))
Run Code Online (Sandbox Code Playgroud)
由于stackoverflow,我把doall放在那里,但仍然没有解决问题.
(defn move-split [[xs ys]] (doall (concat (list (doall (concat xs (list (first ys)))) ) (doall (list (next ys))) )))
Run Code Online (Sandbox Code Playgroud)
注意额外的doalls?在这里,我称之为concat,我通过doall过滤结果.Stackoverflow消失了.
doall似乎不是递归的.这是嵌套列表,也是concat的结果,不会被评估.你怎么看?
Exception in thread "main" java.lang.reflect.InvocationTargetException
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at jline.ConsoleRunner.main(Unknown Source)
Caused by: java.lang.StackOverflowError (bubble_sort2.clj:0)
at clojure.lang.Compiler.eval(Compiler.java:5440)
at clojure.lang.Compiler.load(Compiler.java:5857)
at clojure.lang.Compiler.loadFile(Compiler.java:5820)
at clojure.main$load_script.invoke(main.clj:221)
at clojure.main$script_opt.invoke(main.clj:273)
at clojure.main$main.doInvoke(main.clj:354)
at clojure.lang.RestFn.invoke(RestFn.java:409)
at clojure.lang.Var.invoke(Var.java:365)
at clojure.lang.AFn.applyToHelper(AFn.java:163)
at clojure.lang.Var.applyTo(Var.java:482)
at clojure.main.main(main.java:37)
... 5 more
Caused by: java.lang.StackOverflowError
at clojure.core$seq.invoke(core.clj:122)
at clojure.core$concat$fn__3450.invoke(core.clj:599)
at clojure.lang.LazySeq.sval(LazySeq.java:42)
at clojure.lang.LazySeq.seq(LazySeq.java:56)
at clojure.lang.RT.seq(RT.java:450)
at clojure.core$seq.invoke(core.clj:122)
at clojure.core$concat$fn__3450.invoke(core.clj:599)
at clojure.lang.LazySeq.sval(LazySeq.java:42)
at clojure.lang.LazySeq.seq(LazySeq.java:56)
at clojure.lang.RT.seq(RT.java:450)
at clojure.core$seq.invoke(core.clj:122)
at clojure.core$concat$fn__3450.invoke(core.clj:599)
at clojure.lang.LazySeq.sval(LazySeq.java:42)
at clojure.lang.LazySeq.seq(LazySeq.java:56)
at clojure.lang.RT.seq(RT.java:450)
at clojure.core$seq.invoke(core.clj:122)
at clojure.core$concat$fn__3450.invoke(core.clj:599)
at clojure.lang.LazySeq.sval(LazySeq.java:42)
at clojure.lang.LazySeq.seq(LazySeq.java:56)
at clojure.lang.RT.seq(RT.java:450)
at clojure.core$seq.invoke(core.clj:122)
at clojure.core$concat$fn__3450.invoke(core.clj:599)
Run Code Online (Sandbox Code Playgroud)
你正在连续堆积一堆懒惰的操作,构建一个像这样的表达式
(concat (concat (concat ... [3]) [2]) [1])
Run Code Online (Sandbox Code Playgroud)
或类似的.为了确定结果列表中的第一个元素,编译器必须深入研究您给出的这些函数堆栈.尝试构造你的代码,以便不会发生这种情况,或者每隔一段时间就抛出一次(doall)以强制执行急切/严格的计算.我不能仅仅通过堆栈跟踪来了解更多细节 - 代码会有所帮助.