Clojure:为什么会出现StackOverflower错误?

Clojure:为什么会出现StackOverflower错误?,clojure,Clojure,我知道展平可能是一种更好的方法,但我仍然很好奇为什么这会导致错误。这是因为产生了一个惰性序列 那么,当你打电话的时候 (reduce concat (repeat 10000 [])) 除非您试图使用结果,否则不会进行实际的连接 因此,您的代码创建10000个嵌套的惰性序列,从而导致StackOverflow错误 我可以看到两种防止它抛出错误的方法 第一种方法是使用以下方法强制执行concat: 第二种方法是使用贪婪而不是懒惰concat: (reduce (comp doall concat

我知道展平可能是一种更好的方法,但我仍然很好奇为什么这会导致错误。

这是因为产生了一个惰性序列

那么,当你打电话的时候

(reduce concat (repeat 10000 []))
除非您试图使用结果,否则不会进行实际的连接

因此,您的代码创建10000个嵌套的惰性序列,从而导致StackOverflow错误

我可以看到两种防止它抛出错误的方法

第一种方法是使用以下方法强制执行
concat

第二种方法是使用贪婪而不是懒惰
concat

(reduce (comp doall concat) (repeat 10000 []))
更新 至于您关于使用
展平
的建议,这不是一个好的解决方案,因为
展平
是递归的,所以它也会尝试展平所有嵌套集合。考虑下面的例子:

(reduce into (repeat 10000 []))
它将生成展平序列
(11)
,而不是级联序列
([1][1][1])

我认为最好的解决方案是使用
concat
apply

(flatten (repeat 3 [[1]]))

因为它将生成单个延迟序列,而不会抛出StackOverflow错误。

concat
是延迟的,所以所有对concat的调用都会被保存,直到结果被使用为止
doall
强制执行惰性序列并可防止此错误:

(apply concat (repeat 10000 []))

我在回答中添加了一点关于“展平”的内容。谢谢Leonid,
apply concat
是一个很好的解决方案。同意展平。展平几乎从来都不是正确的做法。@leonid beschastny为什么“10000个嵌套的惰性序列”会导致堆栈溢出错误?@Thumbnail,因为惰性序列只是生成另一个序列的函数。因此,执行这种惰性序列将产生10000个嵌套函数调用,这正是堆栈溢出的情况。@Thumbnail当您调用
(lazy seq x)
clojure创建一个函数,该函数在调用时将产生
x
(如果
x
不是序列,则抛出一个错误)。它不知道什么是
x
。因此,如果
x
是另一个惰性序列,则需要另一个函数调用来查找其中的内容。在我们的例子中,需要10000个嵌套调用才能发现序列实际上是空的。。。
(apply concat (repeat 10000 []))
user> (reduce concat (repeat 10000 []))
StackOverflowError   clojure.lang.RT.seq (RT.java:484)
user> (reduce (comp doall concat) (repeat 10000 []))
()