@@ -70,7 +70,7 @@ object Decorators {
70
70
NoSymbol
71
71
}
72
72
73
- final val MaxFilterRecursions = 1000
73
+ final val MaxFilterRecursions = 10
74
74
75
75
/** Implements filterConserve, zipWithConserve methods
76
76
* on lists that avoid duplication of list nodes where feasible.
@@ -105,24 +105,38 @@ object Decorators {
105
105
}
106
106
107
107
/** 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.
110
109
*/
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
114
116
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
119
133
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
126
140
127
141
/** Like `xs.lazyZip(ys).map(f)`, but returns list `xs` itself
128
142
* - instead of a copy - if function `f` maps all elements of
0 commit comments