Permalink
Browse files

CLJS-587: stack overflow on lazy seqs

deftype now support ^:mutable, no need for lazy-seq-value helper
hack. More closely follow LazySeq.java design. -seq now loops on LazySeq
to avoid stack overflows. Improved LazySeq perf! Added test.
  • Loading branch information...
1 parent 9f5df09 commit 4396e31026338c1b347a0bf833a9077fde88d9a5 @swannodette swannodette committed Sep 26, 2013
Showing with 33 additions and 13 deletions.
  1. +30 −13 src/cljs/cljs/core.cljs
  2. +3 −0 test/cljs/cljs/core_test.cljs
@@ -2061,32 +2061,42 @@ reduces them without incurring seq initialization"
:else (Keyword. nil name name nil)))
([ns name] (Keyword. ns name (str (when ns (str ns "/")) name) nil)))
-(defn- lazy-seq-value [lazy-seq]
- (let [x (.-x lazy-seq)]
- (if ^boolean (.-realized lazy-seq)
- x
- (do
- (set! (.-x lazy-seq) (x))
- (set! (.-realized lazy-seq) true)
- (.-x lazy-seq)))))
-(deftype LazySeq [meta realized x ^:mutable __hash]
+(deftype LazySeq [meta ^:mutable realized ^:mutable x ^:mutable __hash]
Object
(toString [coll]
(pr-str* coll))
+ (sval [coll]
+ (if ^boolean realized
+ x
+ (do
+ (set! x (x))
+ (set! realized true)
+ x)))
+
IWithMeta
(-with-meta [coll meta] (LazySeq. meta realized x __hash))
IMeta
(-meta [coll] meta)
ISeq
- (-first [coll] (first (lazy-seq-value coll)))
- (-rest [coll] (rest (lazy-seq-value coll)))
+ (-first [coll]
+ (-seq coll)
+ (when-not (nil? x)
+ (-first ^not-native x)))
+ (-rest [coll]
+ (-seq coll)
+ (if-not (nil? x)
+ (-rest ^not-native x)
+ ()))
INext
- (-next [coll] (-seq (-rest coll)))
+ (-next [coll]
+ (-seq coll)
+ (when-not (nil? x)
+ (-next ^not-native x)))
ICollection
(-conj [coll o] (cons o coll))
@@ -2103,7 +2113,14 @@ reduces them without incurring seq initialization"
ISeqable
(-seq [coll]
- (seq (lazy-seq-value coll)))
+ (.sval coll)
+ (when-not (nil? x)
+ (loop [ls x]
+ (if (instance? LazySeq ls)
+ (recur (.sval ls))
+ (do (set! x ls)
+ (when-not (nil? x)
+ (-seq ^not-native x)))))))
IReduce
(-reduce [coll f] (seq-reduce f coll))
@@ -1948,5 +1948,8 @@
(def foo580 {:a (fn []) :b (fn [] (foo580 :a))})
(assert (nil? (((:b foo580)))))
+ ;; CLJS-587
+ (assert (== (first (filter #(== % 9999) (range))) 9999))
+
:ok
)

0 comments on commit 4396e31

Please sign in to comment.