Skip to content

Commit 97debea

Browse files
committed
Allow Lst of Array
1 parent 4c8ec5d commit 97debea

File tree

2 files changed

+41
-25
lines changed

2 files changed

+41
-25
lines changed

tests/run/lst/Lst.scala

+40-25
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,13 @@ import printing.{Printer, Texts}
55
import Texts.Text
66
import collection.mutable.{ListBuffer, StringBuilder}
77

8-
98
/** A lightweight class for lists, optimized for short and medium lengths.
109
* A list is represented at runtime as
1110
*
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
1515
*/
1616
class Lst[+T](val elems: Any) extends AnyVal {
1717
import Lst._
@@ -68,8 +68,8 @@ class Lst[+T](val elems: Any) extends AnyVal {
6868
val newElems = new Arr(elems.length)
6969
var i = 0
7070
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))
7373
}
7474
}
7575

@@ -89,8 +89,8 @@ class Lst[+T](val elems: Any) extends AnyVal {
8989
}
9090
i += 1
9191
}
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))
9494
}
9595

9696
def flatMap[U](f: T => Lst[U]): Lst[U] = elems match {
@@ -121,9 +121,9 @@ class Lst[+T](val elems: Any) extends AnyVal {
121121
j += ys.length
122122
i += 1
123123
}
124-
new Lst[U](newElems)
124+
multi[U](newElems)
125125
}
126-
case elem: T @ unchecked => new Lst[U](f(elem).elems)
126+
case elem: T @ unchecked => f(elem)
127127
}
128128

129129
def filter(p: T => Boolean): Lst[T] = elems match {
@@ -214,7 +214,7 @@ class Lst[+T](val elems: Any) extends AnyVal {
214214
newElems(elems.length - 1 - i) = elem(i)
215215
i += 1
216216
}
217-
new Lst[T](newElems)
217+
multi[T](newElems)
218218
case _ => this
219219
}
220220

@@ -252,7 +252,7 @@ class Lst[+T](val elems: Any) extends AnyVal {
252252
val newElems = new Arr(len1 + len2)
253253
this.copyToArray(newElems, 0)
254254
that.copyToArray(newElems, len1)
255-
new Lst[U](newElems)
255+
multi[U](newElems)
256256
}
257257

258258
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 {
264264
case elems2: Arr => def elem2(i: Int) = elems2(i).asInstanceOf[U]
265265
val len = elems1.length min elems2.length
266266
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)))
268268
else {
269269
var newElems: Arr = null
270270
var i = 0
@@ -279,17 +279,17 @@ class Lst[+T](val elems: Any) extends AnyVal {
279279
}
280280
i += 1
281281
}
282-
new Lst[V](newElems)
282+
multi[V](newElems)
283283
}
284284
case elem2: U @unchecked =>
285-
new Lst[V](op(elem1(0), elem2))
285+
single[V](op(elem1(0), elem2))
286286
}
287287
case elem1: T @unchecked =>
288288
that.elems match {
289289
case null => Empty
290290
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))
293293
}
294294
}
295295

@@ -301,9 +301,9 @@ class Lst[+T](val elems: Any) extends AnyVal {
301301
val newElems = new Arr(elems.length)
302302
var i = 0
303303
while (i < elems.length) { newElems(i) = (elem(i), i); i += 1 }
304-
new Lst[(T, Int)](newElems)
304+
multi[(T, Int)](newElems)
305305
case elem: T @unchecked =>
306-
new Lst[(T, Int)]((elem, 0))
306+
single[(T, Int)]((elem, 0))
307307
}
308308

309309
def corresponds[U](that: Lst[U])(p: (T, U) => Boolean): Boolean =
@@ -381,7 +381,7 @@ object Lst {
381381

382382
def apply[T](): Lst[T] = Empty
383383

384-
def apply[T](x0: T): Lst[T] = new Lst[T](x0)
384+
def apply[T](x0: T): Lst[T] = single[T](x0)
385385

386386
def apply[T](x0: T, x1: T): Lst[T] = {
387387
val elems = new Arr(2)
@@ -427,12 +427,12 @@ object Lst {
427427

428428
class Buffer[T] {
429429
private var len = 0
430-
private var elem: T = _
430+
private var elem: Any = _
431431
private var elems: Arr = _
432432

433433
def size = len
434434

435-
/** pre: len > 0, n > 1 */
435+
/** pre: len > 0, n >= 1 */
436436
private def ensureSize(n: Int) =
437437
if (len == 1) {
438438
elems = new Arr(n `max` 16)
@@ -459,7 +459,9 @@ object Lst {
459459
xs.elems match {
460460
case null => this
461461
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
463465
else {
464466
ensureSize(len + elems2.length)
465467
System.arraycopy(elems2, 0, elems, len, elems2.length)
@@ -472,17 +474,30 @@ object Lst {
472474

473475
def toLst: Lst[T] =
474476
if (len == 0) Empty
475-
else if (len == 1) new Lst[T](elem)
477+
else if (len == 1) single(elem)
476478
else _fromArray(elems, 0, len)
477479

478480
def clear() =
479481
len = 0
480482
}
481483

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+
482497
private def _fromArray[T](elems: Arr, start: Int, end: Int): Lst[T] = {
483498
val len = end - start
484499
if (len <= 0) Empty
485-
else if (len == 1) new Lst[T](elems(start))
500+
else if (len == 1) single[T](elems(start))
486501
else if (start == 0 && end == elems.length) new Lst[T](elems)
487502
else {
488503
val newElems = new Arr(len)

tests/run/lst/LstTest.check

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
testing

0 commit comments

Comments
 (0)