Skip to content
This repository was archived by the owner on Dec 22, 2021. It is now read-only.

Commit f5041c6

Browse files
committed
Additional methods and workarounds for Scala 2.12 and Dotty issues
1 parent 633946a commit f5041c6

File tree

2 files changed

+139
-9
lines changed

2 files changed

+139
-9
lines changed

collections/src/main/scala/strawman/collection/ArrayOps.scala

Lines changed: 135 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
package strawman
22
package collection
33

4-
import scala.{AnyVal, Array, Char, Int, throws, Boolean, Serializable, Unit, `inline`, Option, Some, None, PartialFunction}
4+
import scala.{AnyVal, Array, Char, Int, throws, Boolean, Serializable, Unit, `inline`, Option, Some, None, PartialFunction, ArrayIndexOutOfBoundsException, NoSuchElementException, AnyRef}
5+
import scala.Predef.{implicitly, classOf}
56
import java.lang.String
67
import mutable.ArrayBuilder
78
import scala.reflect.ClassTag
8-
import scala.math.{max, min}
9+
import scala.math.{max, min, Ordering}
910

1011
object ArrayOps {
1112
/** A lazy filtered array. No filtering is applied until one of `foreach`, `map` or `flatMap` is called. */
@@ -69,6 +70,28 @@ object ArrayOps {
6970
/** Creates a new non-strict filter which combines this filter with the given predicate. */
7071
def withFilter(q: A => Boolean): WithFilter[A] = new WithFilter[A](a => p(a) && q(a), xs)
7172
}
73+
74+
private class ArrayIterator[A](private[this] val xs: Array[A]) extends Iterator[A] {
75+
private[this] var pos = 0
76+
def hasNext: Boolean = pos < xs.length
77+
def next(): A = try {
78+
val r = xs(pos)
79+
pos += 1
80+
r
81+
} catch { case _: ArrayIndexOutOfBoundsException => throw new NoSuchElementException }
82+
}
83+
84+
private class GroupedIterator[A](xs: Array[A]) extends Iterator[Array[A]] {
85+
private[this] var pos = 0
86+
def hasNext: Boolean = pos < xs.length
87+
def next(): Array[A] = {
88+
if(pos >= xs.length) throw new NoSuchElementException
89+
val r = xs.slice(pos, pos+size)
90+
pos += size
91+
r
92+
}
93+
}
94+
7295
}
7396

7497
/** This class serves as a wrapper for `Array`s with many of the operations found in
@@ -179,6 +202,41 @@ final class ArrayOps[A](val xs: Array[A]) extends AnyVal {
179202
/** The rest of the array without its `n` last elements. */
180203
def dropRight(n: Int): Array[A] = take(xs.length - max(n, 0))
181204

205+
/** Takes longest prefix of elements that satisfy a predicate.
206+
*
207+
* @param p The predicate used to test elements.
208+
* @return the longest prefix of this array whose elements all satisfy
209+
* the predicate `p`.
210+
*/
211+
def takeWhile(p: A => Boolean): Array[A] = {
212+
val i = indexWhere(x => !p(x))
213+
val hi = if(i < 0) xs.length else i
214+
slice(0, hi)
215+
}
216+
217+
/** Drops longest prefix of elements that satisfy a predicate.
218+
*
219+
* @param p The predicate used to test elements.
220+
* @return the longest suffix of this array whose first element
221+
* does not satisfy the predicate `p`.
222+
*/
223+
def dropWhile(p: A => Boolean): Array[A] = {
224+
val i = indexWhere(x => !p(x))
225+
val lo = if(i < 0) xs.length else i
226+
slice(lo, xs.length)
227+
}
228+
229+
def iterator(): Iterator[A] = new ArrayOps.ArrayIterator[A](xs)
230+
231+
/** Partitions elements in fixed size arrays.
232+
* @see [[scala.collection.Iterator]], method `grouped`
233+
*
234+
* @param size the number of elements per group
235+
* @return An iterator producing arrays of size `size`, except the
236+
* last will be less than size `size` if the elements don't divide evenly.
237+
*/
238+
def grouped(size: Int): Iterator[Array[A]] = new ArrayOps.GroupedIterator[A](xs)
239+
182240
/** Splits this array into two at a given position.
183241
* Note: `c splitAt n` is equivalent to `(c take n, c drop n)`.
184242
*
@@ -228,6 +286,78 @@ final class ArrayOps[A](val xs: Array[A]) extends AnyVal {
228286
res.result()
229287
}
230288

289+
/** Selects all elements of this array which do not satisfy a predicate.
290+
*
291+
* @param pred the predicate used to test elements.
292+
* @return a new array consisting of all elements of this array that do not satisfy the given predicate `pred`.
293+
*/
294+
def filterNot(p: A => Boolean): Array[A] = filter(x => !p(x))
295+
296+
/** Sorts this array according to an Ordering.
297+
*
298+
* The sort is stable. That is, elements that are equal (as determined by
299+
* `lt`) appear in the same order in the sorted sequence as in the original.
300+
*
301+
* @see [[scala.math.Ordering]]
302+
*
303+
* @param ord the ordering to be used to compare elements.
304+
* @return an array consisting of the elements of this array
305+
* sorted according to the ordering `ord`.
306+
*/
307+
def sorted[B >: A](implicit ord: Ordering[B]): Array[A] = {
308+
val len = xs.length
309+
if(xs.getClass.getComponentType.isPrimitive && len > 1) {
310+
// need to copy into a boxed representation to use Java's Arrays.sort
311+
val a = new Array[AnyRef](len)
312+
var i = 0
313+
while(i < len) {
314+
a(i) = xs(i).asInstanceOf[AnyRef]
315+
i += 1
316+
}
317+
java.util.Arrays.sort(a, ord.asInstanceOf[Ordering[AnyRef]])
318+
val res = new Array[A](len)
319+
i = 0
320+
while(i < len) {
321+
res(i) = a(i).asInstanceOf[A]
322+
i += 1
323+
}
324+
res
325+
} else {
326+
val copy = slice(0, len)
327+
if(len > 1)
328+
java.util.Arrays.sort(copy.asInstanceOf[Array[AnyRef]], ord.asInstanceOf[Ordering[AnyRef]])
329+
copy
330+
}
331+
}
332+
333+
/** Sorts this array according to a comparison function.
334+
*
335+
* The sort is stable. That is, elements that are equal (as determined by
336+
* `lt`) appear in the same order in the sorted sequence as in the original.
337+
*
338+
* @param lt the comparison function which tests whether
339+
* its first argument precedes its second argument in
340+
* the desired ordering.
341+
* @return an array consisting of the elements of this array
342+
* sorted according to the comparison function `lt`.
343+
*/
344+
def sortWith(lt: (A, A) => Boolean): Array[A] = sorted(Ordering.fromLessThan(lt))
345+
346+
/** Sorts this array according to the Ordering which results from transforming
347+
* an implicitly given Ordering with a transformation function.
348+
*
349+
* @see [[scala.math.Ordering]]
350+
* @param f the transformation function mapping elements
351+
* to some other domain `B`.
352+
* @param ord the ordering assumed on domain `B`.
353+
* @tparam B the target type of the transformation `f`, and the type where
354+
* the ordering `ord` is defined.
355+
* @return an array consisting of the elements of this array
356+
* sorted according to the ordering where `x < y` if
357+
* `ord.lt(f(x), f(y))`.
358+
*/
359+
def sortBy[B](f: A => B)(implicit ord: Ordering[B]): Array[A] = sorted(ord on f)
360+
231361
/** Creates a non-strict filter of this array.
232362
*
233363
* Note: the difference between `c filter p` and `c withFilter p` is that
@@ -443,8 +573,8 @@ final class ArrayOps[A](val xs: Array[A]) extends AnyVal {
443573
* @return a new array containing pairs consisting of corresponding elements of this array and `that`.
444574
* The length of the returned array is the minimum of the lengths of this array and `that`.
445575
*/
446-
def zip[B: ClassTag](that: Iterable[B]): Array[(A, B)] = {
447-
val b = new ArrayBuilder.ofRef[(A, B)]
576+
def zip[B](that: Iterable[B]): Array[(A, B)] = {
577+
val b = new ArrayBuilder.ofRef[(A, B)]()(ClassTag(classOf[(_, _)]).asInstanceOf[ClassTag[(A, B)]])
448578
val k = that.knownSize
449579
b.sizeHint(if(k >= 0) min(k, xs.length) else xs.length)
450580
var i = 0
@@ -589,7 +719,7 @@ final class ArrayOps[A](val xs: Array[A]) extends AnyVal {
589719
val a3 = new Array[A3](xs.length)
590720
var i = 0
591721
while (i < xs.length) {
592-
val e = xs(i)
722+
val e = xs(i).asInstanceOf[(A1, A2, A3)]
593723
a1(i) = e._1
594724
a2(i) = e._2
595725
a3(i) = e._3

collections/src/main/scala/strawman/collection/concurrent/TrieMap.scala

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -582,19 +582,19 @@ private[collection] final class CNode[K, V](val bitmap: Int, val array: Array[Ba
582582
private[concurrent] def string(lev: Int): String = "CNode %x\n%s".format(bitmap, array.map(_.string(lev + 1)).mkString("\n"))
583583

584584
/* quiescently consistent - don't call concurrently to anything involving a GCAS!! */
585-
private def collectElems: Seq[(K, V)] = array flatMap {
585+
private def collectElems: Seq[(K, V)] = array.flatMap({
586586
case sn: SNode[K, V] => Some(sn.kvPair): IterableOnce[(K, V)]
587587
case in: INode[K, V] => in.mainnode match {
588588
case tn: TNode[K, V] => Some(tn.kvPair): IterableOnce[(K, V)]
589589
case ln: LNode[K, V] => ln.entries.to(immutable.List)
590590
case cn: CNode[K, V] => cn.collectElems
591591
}
592-
}
592+
}: (BasicNode => IterableOnce[(K, V)])) //TODO remove type annotatation in 2.13
593593

594-
private def collectLocalElems: Seq[String] = array flatMap {
594+
private def collectLocalElems: Seq[String] = array.flatMap({
595595
case sn: SNode[K, V] => Some(sn.kvPair._2.toString): IterableOnce[String]
596596
case in: INode[K, V] => Some(scala.Predef.augmentString(in.toString).drop(14) + "(" + in.gen + ")"): IterableOnce[String]
597-
}
597+
}: (BasicNode => IterableOnce[String])) //TODO remove type annotatation in 2.13
598598

599599
override def toString = {
600600
val elems = collectLocalElems

0 commit comments

Comments
 (0)