@@ -70,7 +70,7 @@ object Decorators {
7070 NoSymbol
7171 }
7272
73- final val MaxFilterRecursions = 1000
73+ final val MaxFilterRecursions = 10
7474
7575 /** Implements filterConserve, zipWithConserve methods
7676 * on lists that avoid duplication of list nodes where feasible.
@@ -105,24 +105,38 @@ object Decorators {
105105 }
106106
107107 /** Like `xs filter p` but returns list `xs` itself - instead of a copy -
108- * if `p` is true for all elements and `xs` is not longer
109- * than `MaxFilterRecursions`.
108+ * if `p` is true for all elements.
110109 */
111- def filterConserve (p : T => Boolean ): List [T ] = {
112- def loop (xs : List [T ], nrec : Int ): List [T ] = xs match {
113- case Nil => xs
110+ def filterConserve (p : T => Boolean ): List [T ] =
111+
112+ def addAll (buf : ListBuffer [T ], from : List [T ], until : List [T ]): ListBuffer [T ] =
113+ if from eq until then buf else addAll(buf += from.head, from.tail, until)
114+
115+ def loopWithBuffer (buf : ListBuffer [T ], xs : List [T ]): List [T ] = xs match
114116 case x :: xs1 =>
115- if (nrec < MaxFilterRecursions ) {
116- val ys1 = loop(xs1, nrec + 1 )
117- if (p(x))
118- if (ys1 eq xs1) xs else x :: ys1
117+ if p(x) then buf += x
118+ loopWithBuffer(buf, xs1)
119+ case nil => buf.toList
120+
121+ def loop (keep : List [T ], explore : List [T ], keepCount : Int , recCount : Int ): List [T ] =
122+ explore match
123+ case x :: rest =>
124+ if p(x) then
125+ loop(keep, rest, keepCount + 1 , recCount)
126+ else if keepCount <= 3 && recCount <= MaxFilterRecursions then
127+ val rest1 = loop(rest, rest, 0 , recCount + 1 )
128+ keepCount match
129+ case 0 => rest1
130+ case 1 => keep.head :: rest1
131+ case 2 => keep.head :: keep.tail.head :: rest1
132+ case 3 => val tl = keep.tail; keep.head :: tl.head :: tl.tail.head :: rest1
119133 else
120- ys1
121- }
122- else xs filter p
123- }
124- loop(xs, 0 )
125- }
134+ loopWithBuffer(addAll( new ListBuffer [ T ], keep, explore), rest)
135+ case nil =>
136+ keep
137+
138+ loop(xs, xs, 0 , 0 )
139+ end filterConserve
126140
127141 /** Like `xs.lazyZip(ys).map(f)`, but returns list `xs` itself
128142 * - instead of a copy - if function `f` maps all elements of
0 commit comments