【问题标题】:reduce and map on accumulator produces stack overflow累加器上的reduce和map会产生堆栈溢出
【发布时间】:2016-09-21 07:28:04
【问题描述】:

为什么我需要在这段代码中将map替换为mapv以防止堆栈溢出:

#!/bin/bash lein-exec                                                           


(println (reduce (fn [acc _]                                                    
                   ;;(mapv #(inc %) acc))                                       
                   (map #(inc %) acc))                                          
                 (repeat 2 0)                                                   
                 (range (long 1e6))))           

~

我不明白 acc 在懒惰时是如何处理的。感谢您的洞察力。

【问题讨论】:

    标签: clojure stack-overflow lazy-evaluation


    【解决方案1】:

    基本上,你得到的是大量嵌套的惰性序列,当被戳时,会导致堆栈溢出。

    让我们看一个更小的例子:

    (reduce (fn [acc _]
              (map inc acc))
            (repeat 2 0)
            (range 3))
    

    由于map是懒惰的,所以上面的结果将是下一个:

    (map inc (map inc (map inc (0 0)))
    

    所以你不是急切地将accinc 映射,而只是将惰性序列放在另一个中,这将在以后实现。

    回到range1e6 的原始示例,结果如下:

    (map inc 
        (map inc 
             (<... rougly 1e6 nested lazy sequences here ...>
                (map inc (0 0))) ...)
    

    实现这一点会消耗大约1e6堆栈帧,这肯定会导致堆栈溢出。

    如果mapv 不涉及惰性,并且acc 立即实现,因此您的示例结果将在reduce 完成后立即为[1000000 1000000]

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-12-01
      • 1970-01-01
      • 2019-08-25
      • 1970-01-01
      • 2019-05-18
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多