我有以下代码段:
(defn explode [e]
(seq [e e e e]))
(defn f [coll]
(when-first [e coll]
(cons e
(lazy-seq (f (lazy-cat (next coll)
(explode e)))))))
当我尝试访问元素时,出现StackOverflow错误:
user=> (nth (f (seq [1 2 3])) 1000)
3
user=> (nth (f (seq [1 2 3])) 10000)
StackOverflowError clojure.core/concat/fn--3923 (core.clj:678)
如何以不会破坏堆栈的方式构造此代码?
答案 0 :(得分:2)
您必须明确地跟踪剩余的工作,或许是这样:
(defn f [coll]
(letfn [(go [xs q]
(lazy-seq
(cond
(seq xs)
(cons (first xs)
(go (next xs) (conj q (explode (first xs)))))
(seq q)
(go (peek q) (pop q)))))]
(go coll clojure.lang.PersistentQueue/EMPTY)))
来自REPL:
(nth (f [1 2 3]) 1000)
;= 3
(nth (f [1 2 3]) 10000)
;= 2
;; f-orig is f as found in the question text
(= (take 1000 (f-orig [1 2 3])) (take 1000 (f [1 2 3])))
;= true