(reduce concat (repeat 10000 []))
我知道flatten
可能是更好的方法,但我仍然很好奇为什么会导致错误。
答案 0 :(得分:7)
这是因为concat
产生了一个懒惰的序列。
所以,当你打电话时
(concat a b)
除非您尝试使用结果,否则不会进行实际连接。
因此,您的代码会创建10000个嵌套的延迟序列,从而导致StackOverflow错误。
我可以看到两种方法来防止它抛出错误。
第一种方法是使用doall
function强制concat
执行:
(reduce (comp doall concat) (repeat 10000 []))
第二种方法是使用贪婪的into
function而不是懒惰的concat
:
(reduce into (repeat 10000 []))
至于你关于使用flatten
的建议,这不是一个好的解决方案,因为flatten
是递归的,所以它也会尝试展平所有嵌套的集合。请考虑以下示例:
(flatten (repeat 3 [[1]]))
它会产生扁平序列(1 1 1)
,而不是连接的([1] [1] [1])
。
我认为最好的解决方案是将concat
与apply
:
(apply concat (repeat 10000 []))
因为它会产生单个延迟序列而不会抛出StackOverflow错误。
答案 1 :(得分:2)
concat
是懒惰的,所以对concat的所有调用都会被保存,直到使用结果为止。 doall
强制延迟序列并可以防止此错误:
user> (reduce concat (repeat 10000 []))
StackOverflowError clojure.lang.RT.seq (RT.java:484)
user> (reduce (comp doall concat) (repeat 10000 []))
()