Как следует из основного ответа, список concat является правонарушителем. Вызов doall с этим списком в качестве входных данных... приведет к ISeq:
;;insertion sort helper
(defn insert [s k]
;;find the insert point
(let [spl (split-with #(< % k) s)
ret (concat (first spl) (list k) (last spl))]
(doall ret)))
;;insertion sort
(defn insert-sort [s]
(reduce (fn [s k] (insert s k)) '() s))
Но подождите... Последовательность все еще ленивая?
Интересно, что следующий взлом приведенного выше кода указывает на то, что последовательность действительно все еще ленива!
;;insertion sort helper
(defn insert [s k]
;;find the insert point
(let [spl (split-with #(< % k) s)
ret (concat (first spl) (list k) (last spl))
ret2 (doall ret)
_ (println "final " (.getClass ret2))]
ret2))
;;insertion sort
(defn insert-sort [s]
(reduce (fn [s k] (insert s k)) '() s))
Итак, если список все еще ленив, то почему использование doall что-то исправляет?
Функция "doall" не гарантирует возврат "неленивого" списка, но, скорее, она гарантирует, что список, который она ДЕЙСТВИТЕЛЬНО возвращает, будет оценен путем полного обхода.
Таким образом, суть проблемы заключается в множественных вызовах функций, лень, безусловно, связана с этим аспектом кода в вашем исходном вопросе, но это не «первичный» источник переполнения.
person
jayunit100
schedule
26.03.2012