@@ -13,19 +13,21 @@ sealed abstract class Catenable[+A] {
13
13
/** Returns the head and tail of this catenable if non empty, none otherwise. Amortized O(1). */
14
14
final def uncons : Option [(A , Catenable [A ])] = {
15
15
var c : Catenable [A ] = this
16
- var rights : List [Catenable [A ]] = Nil
16
+ val rights = new collection.mutable. ArrayBuffer [Catenable [A ]]
17
17
var result : Option [(A , Catenable [A ])] = null
18
18
while (result eq null ) {
19
19
c match {
20
20
case Empty =>
21
- rights match {
22
- case Nil => result = None
23
- case h :: t => c = h; rights = t
21
+ if (rights.isEmpty) {
22
+ result = None
23
+ } else {
24
+ c = rights.last
25
+ rights.trimEnd(1 )
24
26
}
25
27
case Single (a) =>
26
- val next = if (rights.isEmpty) empty else rights.reverse. reduceLeft((x, y) => Append (y,x))
28
+ val next = if (rights.isEmpty) empty else rights.reduceLeft((x, y) => Append (y,x))
27
29
result = Some (a -> next)
28
- case Append (l, r) => c = l; rights = r :: rights
30
+ case Append (l, r) => c = l; rights + = r
29
31
}
30
32
}
31
33
result
@@ -68,19 +70,21 @@ sealed abstract class Catenable[+A] {
68
70
/** Applies the supplied function to each element, left to right. */
69
71
final def foreach (f : A => Unit ): Unit = {
70
72
var c : Catenable [A ] = this
71
- var rights : List [Catenable [A ]] = Nil
73
+ val rights = new collection.mutable. ArrayBuffer [Catenable [A ]]
72
74
while (c ne null ) {
73
75
c match {
74
76
case Empty =>
75
- rights match {
76
- case Nil => c = null
77
- case h :: t => c = h; rights = t
77
+ if (rights.isEmpty) {
78
+ c = null
79
+ } else {
80
+ c = rights.last
81
+ rights.trimEnd(1 )
78
82
}
79
83
case Single (a) =>
80
84
f(a)
81
- c = if (rights.isEmpty) Empty else rights.reverse. reduceLeft((x, y) => Append (y,x))
82
- rights = Nil
83
- case Append (l, r) => c = l; rights = r :: rights
85
+ c = if (rights.isEmpty) Empty else rights.reduceLeft((x, y) => Append (y,x))
86
+ rights.clear()
87
+ case Append (l, r) => c = l; rights + = r
84
88
}
85
89
}
86
90
}
@@ -125,14 +129,21 @@ object Catenable {
125
129
126
130
/** Creates a catenable from the specified elements. */
127
131
def apply [A ](as : A * ): Catenable [A ] = {
128
- // Assumption: `as` is small enough that calling size doesn't outweigh benefit of calling empty/single
129
- as.size match {
130
- case 0 => empty
131
- case 1 => single(as.head)
132
- case n if n <= 1024 =>
133
- // nb: avoid cost of reversing input if colection is small
134
- as.view.map(single).reduceRight(Append (_, _))
135
- case n => as.view.reverse.map(single).reduceLeft((x, y) => Append (y, x))
132
+ as match {
133
+ case w : collection.mutable.WrappedArray [A ] =>
134
+ if (w.isEmpty) empty
135
+ else if (w.size == 1 ) single(w.head)
136
+ else {
137
+ val arr : Array [A ] = w.array
138
+ var c : Catenable [A ] = single(arr.last)
139
+ var idx = arr.size - 2
140
+ while (idx >= 0 ) {
141
+ c = Append (single(arr(idx)), c)
142
+ idx -= 1
143
+ }
144
+ c
145
+ }
146
+ case _ => fromSeq(as)
136
147
}
137
148
}
138
149
}
0 commit comments