@@ -5,13 +5,13 @@ import printing.{Printer, Texts}
5
5
import Texts .Text
6
6
import collection .mutable .{ListBuffer , StringBuilder }
7
7
8
-
9
8
/** A lightweight class for lists, optimized for short and medium lengths.
10
9
* A list is represented at runtime as
11
10
*
12
- * If it is empty: the value `Lst.Empty`
13
- * If it contains one element: the element itself
14
- * If it contains more elements: an Array[Any] containing the elements
11
+ * If it is empty: the value `Lst.Empty`
12
+ * If it contains one element,
13
+ * and the element is not an array: the element itself
14
+ * Otherwise: an Array[Any] containing the elements
15
15
*/
16
16
class Lst [+ T ](val elems : Any ) extends AnyVal {
17
17
import Lst ._
@@ -68,8 +68,8 @@ class Lst[+T](val elems: Any) extends AnyVal {
68
68
val newElems = new Arr (elems.length)
69
69
var i = 0
70
70
while (i < elems.length) { newElems(i) = op(elem(i)); i += 1 }
71
- new Lst [U ](newElems)
72
- case elem : T @ unchecked => new Lst [U ](op(elem))
71
+ multi [U ](newElems)
72
+ case elem : T @ unchecked => single [U ](op(elem))
73
73
}
74
74
}
75
75
@@ -89,8 +89,8 @@ class Lst[+T](val elems: Any) extends AnyVal {
89
89
}
90
90
i += 1
91
91
}
92
- if (newElems == null ) this .asInstanceOf [Lst [U ]] else new Lst [U ](newElems)
93
- case elem : T @ unchecked => new Lst [U ](f(elem))
92
+ if (newElems == null ) this .asInstanceOf [Lst [U ]] else multi [U ](newElems)
93
+ case elem : T @ unchecked => single [U ](f(elem))
94
94
}
95
95
96
96
def flatMap [U ](f : T => Lst [U ]): Lst [U ] = elems match {
@@ -121,9 +121,9 @@ class Lst[+T](val elems: Any) extends AnyVal {
121
121
j += ys.length
122
122
i += 1
123
123
}
124
- new Lst [U ](newElems)
124
+ multi [U ](newElems)
125
125
}
126
- case elem : T @ unchecked => new Lst [ U ]( f(elem).elems )
126
+ case elem : T @ unchecked => f(elem)
127
127
}
128
128
129
129
def filter (p : T => Boolean ): Lst [T ] = elems match {
@@ -214,7 +214,7 @@ class Lst[+T](val elems: Any) extends AnyVal {
214
214
newElems(elems.length - 1 - i) = elem(i)
215
215
i += 1
216
216
}
217
- new Lst [T ](newElems)
217
+ multi [T ](newElems)
218
218
case _ => this
219
219
}
220
220
@@ -252,7 +252,7 @@ class Lst[+T](val elems: Any) extends AnyVal {
252
252
val newElems = new Arr (len1 + len2)
253
253
this .copyToArray(newElems, 0 )
254
254
that.copyToArray(newElems, len1)
255
- new Lst [U ](newElems)
255
+ multi [U ](newElems)
256
256
}
257
257
258
258
def zipWith [U , V ](that : Lst [U ])(op : (T , U ) => V ): Lst [V ] =
@@ -264,7 +264,7 @@ class Lst[+T](val elems: Any) extends AnyVal {
264
264
case elems2 : Arr => def elem2 (i : Int ) = elems2(i).asInstanceOf [U ]
265
265
val len = elems1.length min elems2.length
266
266
if (len == 0 ) Empty
267
- else if (len == 1 ) new Lst [V ](op(elem1(0 ), elem2(0 )))
267
+ else if (len == 1 ) single [V ](op(elem1(0 ), elem2(0 )))
268
268
else {
269
269
var newElems : Arr = null
270
270
var i = 0
@@ -279,17 +279,17 @@ class Lst[+T](val elems: Any) extends AnyVal {
279
279
}
280
280
i += 1
281
281
}
282
- new Lst [V ](newElems)
282
+ multi [V ](newElems)
283
283
}
284
284
case elem2 : U @ unchecked =>
285
- new Lst [V ](op(elem1(0 ), elem2))
285
+ single [V ](op(elem1(0 ), elem2))
286
286
}
287
287
case elem1 : T @ unchecked =>
288
288
that.elems match {
289
289
case null => Empty
290
290
case elems2 : Arr => def elem2 (i : Int ) = elems2(i).asInstanceOf [U ]
291
- new Lst [V ](op(elem1, elem2(0 )))
292
- case elem2 : U @ unchecked => new Lst [V ](op(elem1, elem2))
291
+ single [V ](op(elem1, elem2(0 )))
292
+ case elem2 : U @ unchecked => single [V ](op(elem1, elem2))
293
293
}
294
294
}
295
295
@@ -301,9 +301,9 @@ class Lst[+T](val elems: Any) extends AnyVal {
301
301
val newElems = new Arr (elems.length)
302
302
var i = 0
303
303
while (i < elems.length) { newElems(i) = (elem(i), i); i += 1 }
304
- new Lst [(T , Int )](newElems)
304
+ multi [(T , Int )](newElems)
305
305
case elem : T @ unchecked =>
306
- new Lst [(T , Int )]((elem, 0 ))
306
+ single [(T , Int )]((elem, 0 ))
307
307
}
308
308
309
309
def corresponds [U ](that : Lst [U ])(p : (T , U ) => Boolean ): Boolean =
@@ -381,7 +381,7 @@ object Lst {
381
381
382
382
def apply [T ](): Lst [T ] = Empty
383
383
384
- def apply [T ](x0 : T ): Lst [T ] = new Lst [T ](x0)
384
+ def apply [T ](x0 : T ): Lst [T ] = single [T ](x0)
385
385
386
386
def apply [T ](x0 : T , x1 : T ): Lst [T ] = {
387
387
val elems = new Arr (2 )
@@ -427,12 +427,12 @@ object Lst {
427
427
428
428
class Buffer [T ] {
429
429
private var len = 0
430
- private var elem : T = _
430
+ private var elem : Any = _
431
431
private var elems : Arr = _
432
432
433
433
def size = len
434
434
435
- /** pre: len > 0, n > 1 */
435
+ /** pre: len > 0, n >= 1 */
436
436
private def ensureSize (n : Int ) =
437
437
if (len == 1 ) {
438
438
elems = new Arr (n `max` 16 )
@@ -459,7 +459,9 @@ object Lst {
459
459
xs.elems match {
460
460
case null => this
461
461
case elems2 : Arr =>
462
- if (len == 0 ) elems = elems2
462
+ if (len == 0 && elems2.length != 1 )
463
+ // if elems2.length == 1, elems2 is a wrapped single element list, which has to be unpacked
464
+ elems = elems2
463
465
else {
464
466
ensureSize(len + elems2.length)
465
467
System .arraycopy(elems2, 0 , elems, len, elems2.length)
@@ -472,17 +474,30 @@ object Lst {
472
474
473
475
def toLst : Lst [T ] =
474
476
if (len == 0 ) Empty
475
- else if (len == 1 ) new Lst [ T ] (elem)
477
+ else if (len == 1 ) single (elem)
476
478
else _fromArray(elems, 0 , len)
477
479
478
480
def clear () =
479
481
len = 0
480
482
}
481
483
484
+ private def single [T ](elem : Any ): Lst [T ] = elem match {
485
+ case elem : Arr =>
486
+ val wrapped = new Arr (1 )
487
+ wrapped(0 ) = elem
488
+ new Lst [T ](wrapped)
489
+ case _ =>
490
+ new Lst [T ](elem)
491
+ }
492
+
493
+ private def multi [T ](elems : Array [Any ]) =
494
+ if (elems.length == 1 ) new Lst [T ](elems(0 ))
495
+ else new Lst [T ](elems)
496
+
482
497
private def _fromArray [T ](elems : Arr , start : Int , end : Int ): Lst [T ] = {
483
498
val len = end - start
484
499
if (len <= 0 ) Empty
485
- else if (len == 1 ) new Lst [T ](elems(start))
500
+ else if (len == 1 ) single [T ](elems(start))
486
501
else if (start == 0 && end == elems.length) new Lst [T ](elems)
487
502
else {
488
503
val newElems = new Arr (len)
0 commit comments