为什么我需要在这段代码中用map
替换mapv
以防止堆栈溢出:
#!/bin/bash lein-exec
(println (reduce (fn [acc _]
;;(mapv #(inc %) acc))
(map #(inc %) acc))
(repeat 2 0)
(range (long 1e6))))
〜
我不明白懒惰时如何处理acc
。感谢您的见解。
答案 0 :(得分:4)
基本上,你得到的是大量嵌套的延迟序列,当被戳时,会导致堆栈溢出。
让我们看一下较小的例子:
(reduce (fn [acc _]
(map inc acc))
(repeat 2 0)
(range 3))
由于map
是懒惰的,因此上面的结果将是下一个:
(map inc (map inc (map inc (0 0)))
所以你并不急切地将acc
映射到inc
,而只是将懒惰序列一个放到另一个中,这将在之后实现。
返回range
占用1e6
的原始示例,结果如下:
(map inc
(map inc
(<... rougly 1e6 nested lazy sequences here ...>
(map inc (0 0))) ...)
实现此操作将消耗大约1e6
个堆栈帧,这肯定会导致堆栈溢出。
如果mapv
没有涉及懒惰并立即实现acc
,那么您的示例结果将在[1000000 1000000]
完成后reduce
完成。