@@ -88,16 +88,18 @@ abstract class Chunk[+O] extends Serializable with ChunkPlatform[O] with ChunkRu
88
88
/** Copies the elements of this chunk in to the specified array at the specified start index. */
89
89
def copyToArray [O2 >: O ](xs : Array [O2 ], start : Int = 0 ): Unit
90
90
91
- /** Converts this chunk to a chunk backed by a single array. */
91
+ /** Converts this chunk to a chunk backed by a single array.
92
+ *
93
+ * Alternatively, call `toIndexedChunk` to get back a chunk with guaranteed O(1) indexed lookup
94
+ * while also minimizing copying.
95
+ */
92
96
def compact [O2 >: O ](implicit ct : ClassTag [O2 ]): Chunk .ArraySlice [O2 ] =
93
97
Chunk .ArraySlice (toArray[O2 ], 0 , size)
94
98
95
99
/** Like `compact` but does not require a `ClassTag`. Elements are boxed and stored in an `Array[Any]`. */
96
- def compactUntagged [O2 >: O ]: Chunk .ArraySlice [O2 ] = {
97
- val arr = new Array [Any ](size)
98
- copyToArray(arr, 0 )
99
- Chunk .array(arr).asInstanceOf [Chunk .ArraySlice [O2 ]]
100
- }
100
+ @ deprecated(" Unsound when used with primitives, use compactBoxed instead" , " 3.1.6" )
101
+ def compactUntagged [O2 >: O ]: Chunk .ArraySlice [O2 ] =
102
+ Chunk .ArraySlice (toArray[Any ], 0 , size).asInstanceOf [Chunk .ArraySlice [O2 ]]
101
103
102
104
/** Drops the first `n` elements of this chunk. */
103
105
def drop (n : Int ): Chunk [O ] = splitAt(n)._2
@@ -311,6 +313,21 @@ abstract class Chunk[+O] extends Serializable with ChunkPlatform[O] with ChunkRu
311
313
if (isEmpty) Chain .empty
312
314
else Chain .fromSeq(toList)
313
315
316
+ /** Returns a chunk with guaranteed O(1) lookup by index.
317
+ *
318
+ * Unlike `compact`, this operation does not copy any elements unless this chunk
319
+ * does not provide O(1) lookup by index -- e.g., a chunk built via 1 or more usages
320
+ * of `++`.
321
+ */
322
+ def toIndexedChunk : Chunk [O ] = this match {
323
+ case _ : Chunk .Queue [_] =>
324
+ val b = collection.mutable.Buffer .newBuilder[O ]
325
+ b.sizeHint(size)
326
+ foreach(o => b += o)
327
+ Chunk .buffer(b.result())
328
+ case other => other
329
+ }
330
+
314
331
/** Converts this chunk to a list. */
315
332
def toList : List [O ] =
316
333
if (isEmpty) Nil
@@ -678,6 +695,7 @@ object Chunk
678
695
this .asInstanceOf [ArraySlice [O2 ]]
679
696
else super .compact
680
697
698
+ @ deprecated(" Unsound" , " 3.1.6" )
681
699
override def compactUntagged [O2 >: O ]: ArraySlice [O2 ] =
682
700
if ((classOf [Array [Any ]] eq values.getClass) && offset == 0 && length == values.length)
683
701
this .asInstanceOf [ArraySlice [O2 ]]
@@ -1066,12 +1084,12 @@ object Chunk
1066
1084
}
1067
1085
1068
1086
override def traverse [F [_], O2 ](f : O => F [O2 ])(implicit F : Applicative [F ]): F [Chunk [O2 ]] =
1069
- compactUntagged .traverse(f)
1087
+ toIndexedChunk .traverse(f)
1070
1088
1071
1089
override def traverseFilter [F [_], O2 ](f : O => F [Option [O2 ]])(implicit
1072
1090
F : Applicative [F ]
1073
1091
): F [Chunk [O2 ]] =
1074
- compactUntagged .traverseFilter(f)
1092
+ toIndexedChunk .traverseFilter(f)
1075
1093
}
1076
1094
1077
1095
object Queue {
0 commit comments