2016-09-21 7 views
2

Почему мне нужно заменить map с mapv в этой части кода, чтобы предотвратить переполнение стека:уменьшить карту на аккумуляторе производит переполнение стека

#!/bin/bash lein-exec               


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

~

Я не понимаю, как acc обрабатывается при лени. Спасибо за понимание.

ответ

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 отделки.

 Смежные вопросы

  • Нет связанных вопросов^_^