Compare commits
2 Commits
c0c49089b1
...
2ee6ce0429
Author | SHA1 | Date |
---|---|---|
boB Rudis | 2ee6ce0429 | 3 years ago |
boB Rudis | 11f6e2d96c | 3 years ago |
26 changed files with 7216 additions and 0 deletions
Binary file not shown.
@ -0,0 +1,627 @@ |
|||
/* |
|||
* Scala (https://www.scala-lang.org) |
|||
* |
|||
* Copyright EPFL and Lightbend, Inc. |
|||
* |
|||
* Licensed under Apache License 2.0 |
|||
* (http://www.apache.org/licenses/LICENSE-2.0). |
|||
* |
|||
* See the NOTICE file distributed with this work for |
|||
* additional information regarding copyright ownership. |
|||
*/ |
|||
|
|||
package scala |
|||
|
|||
import scala.collection.generic._ |
|||
import scala.collection.{ mutable, immutable } |
|||
import mutable.{ ArrayBuilder, ArraySeq } |
|||
import scala.reflect.ClassTag |
|||
import scala.runtime.ScalaRunTime.{ array_apply, array_update } |
|||
|
|||
/** Contains a fallback builder for arrays when the element type |
|||
* does not have a class tag. In that case a generic array is built. |
|||
*/ |
|||
class FallbackArrayBuilding { |
|||
|
|||
/** A builder factory that generates a generic array. |
|||
* Called instead of `Array.newBuilder` if the element type of an array |
|||
* does not have a class tag. Note that fallbackBuilder factory |
|||
* needs an implicit parameter (otherwise it would not be dominated in |
|||
* implicit search by `Array.canBuildFrom`). We make sure that |
|||
* implicit search is always successful. |
|||
*/ |
|||
implicit def fallbackCanBuildFrom[T](implicit m: DummyImplicit): CanBuildFrom[Array[_], T, ArraySeq[T]] = |
|||
new CanBuildFrom[Array[_], T, ArraySeq[T]] { |
|||
def apply(from: Array[_]) = ArraySeq.newBuilder[T] |
|||
def apply() = ArraySeq.newBuilder[T] |
|||
} |
|||
} |
|||
|
|||
/** Utility methods for operating on arrays. |
|||
* For example: |
|||
* {{{ |
|||
* val a = Array(1, 2) |
|||
* val b = Array.ofDim[Int](2) |
|||
* val c = Array.concat(a, b) |
|||
* }}} |
|||
* where the array objects `a`, `b` and `c` have respectively the values |
|||
* `Array(1, 2)`, `Array(0, 0)` and `Array(1, 2, 0, 0)`. |
|||
* |
|||
* @author Martin Odersky |
|||
* @since 1.0 |
|||
*/ |
|||
object Array extends FallbackArrayBuilding { |
|||
val emptyBooleanArray = new Array[Boolean](0) |
|||
val emptyByteArray = new Array[Byte](0) |
|||
val emptyCharArray = new Array[Char](0) |
|||
val emptyDoubleArray = new Array[Double](0) |
|||
val emptyFloatArray = new Array[Float](0) |
|||
val emptyIntArray = new Array[Int](0) |
|||
val emptyLongArray = new Array[Long](0) |
|||
val emptyShortArray = new Array[Short](0) |
|||
val emptyObjectArray = new Array[Object](0) |
|||
|
|||
implicit def canBuildFrom[T](implicit tag: ClassTag[T]): CanBuildFrom[Array[_], T, Array[T]] = { |
|||
val cls = tag.runtimeClass |
|||
(if (cls.isPrimitive) { |
|||
cls match { |
|||
case java.lang.Integer.TYPE => cbfIntArray |
|||
case java.lang.Double.TYPE => cbfDoubleArray |
|||
case java.lang.Long.TYPE => cbfLongArray |
|||
case java.lang.Float.TYPE => cbfFloatArray |
|||
case java.lang.Character.TYPE => cbfCharArray |
|||
case java.lang.Byte.TYPE => cbfByteArray |
|||
case java.lang.Short.TYPE => cbfShortArray |
|||
case java.lang.Boolean.TYPE => cbfBooleanArray |
|||
case java.lang.Void.TYPE => cbfUnitArray |
|||
} |
|||
} else if (cls == ObjectClass) { |
|||
cbfObjectArray |
|||
} else { |
|||
refCBF[T with AnyRef](tag.asInstanceOf[ClassTag[T with AnyRef]]) |
|||
}).asInstanceOf[CanBuildFrom[Array[_], T, Array[T]]] |
|||
} |
|||
private[this] val ObjectClass = classOf[Object] |
|||
|
|||
private[this] val cbfBooleanArray = new CanBuildFrom[Array[_], Boolean, Array[Boolean]] { |
|||
def apply(from: Array[_]) = new ArrayBuilder.ofBoolean() |
|||
def apply() = new ArrayBuilder.ofBoolean() |
|||
} |
|||
|
|||
private[this] val cbfByteArray = new CanBuildFrom[Array[_], Byte, Array[Byte]] { |
|||
def apply(from: Array[_]) = new ArrayBuilder.ofByte() |
|||
def apply() = new ArrayBuilder.ofByte() |
|||
} |
|||
|
|||
private[this] val cbfCharArray = new CanBuildFrom[Array[_], Char, Array[Char]] { |
|||
def apply(from: Array[_]) = new ArrayBuilder.ofChar() |
|||
def apply() = new ArrayBuilder.ofChar() |
|||
} |
|||
|
|||
private[this] val cbfDoubleArray = new CanBuildFrom[Array[_], Double, Array[Double]] { |
|||
def apply(from: Array[_]) = new ArrayBuilder.ofDouble() |
|||
def apply() = new ArrayBuilder.ofDouble() |
|||
} |
|||
|
|||
private[this] val cbfFloatArray = new CanBuildFrom[Array[_], Float, Array[Float]] { |
|||
def apply(from: Array[_]) = new ArrayBuilder.ofFloat() |
|||
def apply() = new ArrayBuilder.ofFloat() |
|||
} |
|||
|
|||
private[this] val cbfIntArray = new CanBuildFrom[Array[_], Int, Array[Int]] { |
|||
def apply(from: Array[_]) = new ArrayBuilder.ofInt() |
|||
def apply() = new ArrayBuilder.ofInt() |
|||
} |
|||
|
|||
private[this] val cbfLongArray = new CanBuildFrom[Array[_], Long, Array[Long]] { |
|||
def apply(from: Array[_]) = new ArrayBuilder.ofLong() |
|||
def apply() = new ArrayBuilder.ofLong() |
|||
} |
|||
|
|||
private[this] val cbfShortArray = new CanBuildFrom[Array[_], Short, Array[Short]] { |
|||
def apply(from: Array[_]) = new ArrayBuilder.ofShort() |
|||
def apply() = new ArrayBuilder.ofShort() |
|||
} |
|||
|
|||
private[this] val cbfUnitArray = new CanBuildFrom[Array[_], Unit, Array[Unit]] { |
|||
def apply(from: Array[_]) = new ArrayBuilder.ofUnit() |
|||
def apply() = new ArrayBuilder.ofUnit() |
|||
} |
|||
|
|||
private[this] val cbfObjectArray = refCBF[Object] |
|||
private[this] def refCBF[T <: AnyRef](implicit t: ClassTag[T]): CanBuildFrom[Array[_], T, Array[T]] = |
|||
new CanBuildFrom[Array[_], T, Array[T]] { |
|||
def apply(from: Array[_]) = new ArrayBuilder.ofRef[T]()(t) |
|||
def apply() = new ArrayBuilder.ofRef[T]()(t) |
|||
} |
|||
|
|||
/** |
|||
* Returns a new [[scala.collection.mutable.ArrayBuilder]]. |
|||
*/ |
|||
def newBuilder[T](implicit t: ClassTag[T]): ArrayBuilder[T] = ArrayBuilder.make[T]()(t) |
|||
|
|||
private def slowcopy(src : AnyRef, |
|||
srcPos : Int, |
|||
dest : AnyRef, |
|||
destPos : Int, |
|||
length : Int) { |
|||
var i = srcPos |
|||
var j = destPos |
|||
val srcUntil = srcPos + length |
|||
while (i < srcUntil) { |
|||
array_update(dest, j, array_apply(src, i)) |
|||
i += 1 |
|||
j += 1 |
|||
} |
|||
} |
|||
|
|||
/** Copy one array to another. |
|||
* Equivalent to Java's |
|||
* `System.arraycopy(src, srcPos, dest, destPos, length)`, |
|||
* except that this also works for polymorphic and boxed arrays. |
|||
* |
|||
* Note that the passed-in `dest` array will be modified by this call. |
|||
* |
|||
* @param src the source array. |
|||
* @param srcPos starting position in the source array. |
|||
* @param dest destination array. |
|||
* @param destPos starting position in the destination array. |
|||
* @param length the number of array elements to be copied. |
|||
* |
|||
* @see `java.lang.System#arraycopy` |
|||
*/ |
|||
def copy(src: AnyRef, srcPos: Int, dest: AnyRef, destPos: Int, length: Int) { |
|||
val srcClass = src.getClass |
|||
if (srcClass.isArray && dest.getClass.isAssignableFrom(srcClass)) |
|||
java.lang.System.arraycopy(src, srcPos, dest, destPos, length) |
|||
else |
|||
slowcopy(src, srcPos, dest, destPos, length) |
|||
} |
|||
|
|||
/** Returns an array of length 0 */ |
|||
def empty[T: ClassTag]: Array[T] = new Array[T](0) |
|||
|
|||
/** Creates an array with given elements. |
|||
* |
|||
* @param xs the elements to put in the array |
|||
* @return an array containing all elements from xs. |
|||
*/ |
|||
// Subject to a compiler optimization in Cleanup. |
|||
// Array(e0, ..., en) is translated to { val a = new Array(3); a(i) = ei; a } |
|||
def apply[T: ClassTag](xs: T*): Array[T] = { |
|||
val array = new Array[T](xs.length) |
|||
var i = 0 |
|||
for (x <- xs.iterator) { array(i) = x; i += 1 } |
|||
array |
|||
} |
|||
|
|||
/** Creates an array of `Boolean` objects */ |
|||
// Subject to a compiler optimization in Cleanup, see above. |
|||
def apply(x: Boolean, xs: Boolean*): Array[Boolean] = { |
|||
val array = new Array[Boolean](xs.length + 1) |
|||
array(0) = x |
|||
var i = 1 |
|||
for (x <- xs.iterator) { array(i) = x; i += 1 } |
|||
array |
|||
} |
|||
|
|||
/** Creates an array of `Byte` objects */ |
|||
// Subject to a compiler optimization in Cleanup, see above. |
|||
def apply(x: Byte, xs: Byte*): Array[Byte] = { |
|||
val array = new Array[Byte](xs.length + 1) |
|||
array(0) = x |
|||
var i = 1 |
|||
for (x <- xs.iterator) { array(i) = x; i += 1 } |
|||
array |
|||
} |
|||
|
|||
/** Creates an array of `Short` objects */ |
|||
// Subject to a compiler optimization in Cleanup, see above. |
|||
def apply(x: Short, xs: Short*): Array[Short] = { |
|||
val array = new Array[Short](xs.length + 1) |
|||
array(0) = x |
|||
var i = 1 |
|||
for (x <- xs.iterator) { array(i) = x; i += 1 } |
|||
array |
|||
} |
|||
|
|||
/** Creates an array of `Char` objects */ |
|||
// Subject to a compiler optimization in Cleanup, see above. |
|||
def apply(x: Char, xs: Char*): Array[Char] = { |
|||
val array = new Array[Char](xs.length + 1) |
|||
array(0) = x |
|||
var i = 1 |
|||
for (x <- xs.iterator) { array(i) = x; i += 1 } |
|||
array |
|||
} |
|||
|
|||
/** Creates an array of `Int` objects */ |
|||
// Subject to a compiler optimization in Cleanup, see above. |
|||
def apply(x: Int, xs: Int*): Array[Int] = { |
|||
val array = new Array[Int](xs.length + 1) |
|||
array(0) = x |
|||
var i = 1 |
|||
for (x <- xs.iterator) { array(i) = x; i += 1 } |
|||
array |
|||
} |
|||
|
|||
/** Creates an array of `Long` objects */ |
|||
// Subject to a compiler optimization in Cleanup, see above. |
|||
def apply(x: Long, xs: Long*): Array[Long] = { |
|||
val array = new Array[Long](xs.length + 1) |
|||
array(0) = x |
|||
var i = 1 |
|||
for (x <- xs.iterator) { array(i) = x; i += 1 } |
|||
array |
|||
} |
|||
|
|||
/** Creates an array of `Float` objects */ |
|||
// Subject to a compiler optimization in Cleanup, see above. |
|||
def apply(x: Float, xs: Float*): Array[Float] = { |
|||
val array = new Array[Float](xs.length + 1) |
|||
array(0) = x |
|||
var i = 1 |
|||
for (x <- xs.iterator) { array(i) = x; i += 1 } |
|||
array |
|||
} |
|||
|
|||
/** Creates an array of `Double` objects */ |
|||
// Subject to a compiler optimization in Cleanup, see above. |
|||
def apply(x: Double, xs: Double*): Array[Double] = { |
|||
val array = new Array[Double](xs.length + 1) |
|||
array(0) = x |
|||
var i = 1 |
|||
for (x <- xs.iterator) { array(i) = x; i += 1 } |
|||
array |
|||
} |
|||
|
|||
/** Creates an array of `Unit` objects */ |
|||
def apply(x: Unit, xs: Unit*): Array[Unit] = { |
|||
val array = new Array[Unit](xs.length + 1) |
|||
array(0) = x |
|||
var i = 1 |
|||
for (x <- xs.iterator) { array(i) = x; i += 1 } |
|||
array |
|||
} |
|||
|
|||
/** Creates array with given dimensions */ |
|||
def ofDim[T: ClassTag](n1: Int): Array[T] = |
|||
new Array[T](n1) |
|||
/** Creates a 2-dimensional array */ |
|||
def ofDim[T: ClassTag](n1: Int, n2: Int): Array[Array[T]] = { |
|||
val arr: Array[Array[T]] = (new Array[Array[T]](n1): Array[Array[T]]) |
|||
for (i <- 0 until n1) arr(i) = new Array[T](n2) |
|||
arr |
|||
// tabulate(n1)(_ => ofDim[T](n2)) |
|||
} |
|||
/** Creates a 3-dimensional array */ |
|||
def ofDim[T: ClassTag](n1: Int, n2: Int, n3: Int): Array[Array[Array[T]]] = |
|||
tabulate(n1)(_ => ofDim[T](n2, n3)) |
|||
/** Creates a 4-dimensional array */ |
|||
def ofDim[T: ClassTag](n1: Int, n2: Int, n3: Int, n4: Int): Array[Array[Array[Array[T]]]] = |
|||
tabulate(n1)(_ => ofDim[T](n2, n3, n4)) |
|||
/** Creates a 5-dimensional array */ |
|||
def ofDim[T: ClassTag](n1: Int, n2: Int, n3: Int, n4: Int, n5: Int): Array[Array[Array[Array[Array[T]]]]] = |
|||
tabulate(n1)(_ => ofDim[T](n2, n3, n4, n5)) |
|||
|
|||
/** Concatenates all arrays into a single array. |
|||
* |
|||
* @param xss the given arrays |
|||
* @return the array created from concatenating `xss` |
|||
*/ |
|||
def concat[T: ClassTag](xss: Array[T]*): Array[T] = { |
|||
val b = newBuilder[T] |
|||
b.sizeHint(xss.map(_.length).sum) |
|||
for (xs <- xss) b ++= xs |
|||
b.result() |
|||
} |
|||
|
|||
/** Returns an array that contains the results of some element computation a number |
|||
* of times. |
|||
* |
|||
* Note that this means that `elem` is computed a total of n times: |
|||
* {{{ |
|||
* scala> Array.fill(3){ math.random } |
|||
* res3: Array[Double] = Array(0.365461167592537, 1.550395944913685E-4, 0.7907242137333306) |
|||
* }}} |
|||
* |
|||
* @param n the number of elements desired |
|||
* @param elem the element computation |
|||
* @return an Array of size n, where each element contains the result of computing |
|||
* `elem`. |
|||
*/ |
|||
def fill[T: ClassTag](n: Int)(elem: => T): Array[T] = { |
|||
val b = newBuilder[T] |
|||
b.sizeHint(n) |
|||
var i = 0 |
|||
while (i < n) { |
|||
b += elem |
|||
i += 1 |
|||
} |
|||
b.result() |
|||
} |
|||
|
|||
/** Returns a two-dimensional array that contains the results of some element |
|||
* computation a number of times. |
|||
* |
|||
* @param n1 the number of elements in the 1st dimension |
|||
* @param n2 the number of elements in the 2nd dimension |
|||
* @param elem the element computation |
|||
*/ |
|||
def fill[T: ClassTag](n1: Int, n2: Int)(elem: => T): Array[Array[T]] = |
|||
tabulate(n1)(_ => fill(n2)(elem)) |
|||
|
|||
/** Returns a three-dimensional array that contains the results of some element |
|||
* computation a number of times. |
|||
* |
|||
* @param n1 the number of elements in the 1st dimension |
|||
* @param n2 the number of elements in the 2nd dimension |
|||
* @param n3 the number of elements in the 3nd dimension |
|||
* @param elem the element computation |
|||
*/ |
|||
def fill[T: ClassTag](n1: Int, n2: Int, n3: Int)(elem: => T): Array[Array[Array[T]]] = |
|||
tabulate(n1)(_ => fill(n2, n3)(elem)) |
|||
|
|||
/** Returns a four-dimensional array that contains the results of some element |
|||
* computation a number of times. |
|||
* |
|||
* @param n1 the number of elements in the 1st dimension |
|||
* @param n2 the number of elements in the 2nd dimension |
|||
* @param n3 the number of elements in the 3nd dimension |
|||
* @param n4 the number of elements in the 4th dimension |
|||
* @param elem the element computation |
|||
*/ |
|||
def fill[T: ClassTag](n1: Int, n2: Int, n3: Int, n4: Int)(elem: => T): Array[Array[Array[Array[T]]]] = |
|||
tabulate(n1)(_ => fill(n2, n3, n4)(elem)) |
|||
|
|||
/** Returns a five-dimensional array that contains the results of some element |
|||
* computation a number of times. |
|||
* |
|||
* @param n1 the number of elements in the 1st dimension |
|||
* @param n2 the number of elements in the 2nd dimension |
|||
* @param n3 the number of elements in the 3nd dimension |
|||
* @param n4 the number of elements in the 4th dimension |
|||
* @param n5 the number of elements in the 5th dimension |
|||
* @param elem the element computation |
|||
*/ |
|||
def fill[T: ClassTag](n1: Int, n2: Int, n3: Int, n4: Int, n5: Int)(elem: => T): Array[Array[Array[Array[Array[T]]]]] = |
|||
tabulate(n1)(_ => fill(n2, n3, n4, n5)(elem)) |
|||
|
|||
/** Returns an array containing values of a given function over a range of integer |
|||
* values starting from 0. |
|||
* |
|||
* @param n The number of elements in the array |
|||
* @param f The function computing element values |
|||
* @return A traversable consisting of elements `f(0),f(1), ..., f(n - 1)` |
|||
*/ |
|||
def tabulate[T: ClassTag](n: Int)(f: Int => T): Array[T] = { |
|||
val b = newBuilder[T] |
|||
b.sizeHint(n) |
|||
var i = 0 |
|||
while (i < n) { |
|||
b += f(i) |
|||
i += 1 |
|||
} |
|||
b.result() |
|||
} |
|||
|
|||
/** Returns a two-dimensional array containing values of a given function |
|||
* over ranges of integer values starting from `0`. |
|||
* |
|||
* @param n1 the number of elements in the 1st dimension |
|||
* @param n2 the number of elements in the 2nd dimension |
|||
* @param f The function computing element values |
|||
*/ |
|||
def tabulate[T: ClassTag](n1: Int, n2: Int)(f: (Int, Int) => T): Array[Array[T]] = |
|||
tabulate(n1)(i1 => tabulate(n2)(f(i1, _))) |
|||
|
|||
/** Returns a three-dimensional array containing values of a given function |
|||
* over ranges of integer values starting from `0`. |
|||
* |
|||
* @param n1 the number of elements in the 1st dimension |
|||
* @param n2 the number of elements in the 2nd dimension |
|||
* @param n3 the number of elements in the 3rd dimension |
|||
* @param f The function computing element values |
|||
*/ |
|||
def tabulate[T: ClassTag](n1: Int, n2: Int, n3: Int)(f: (Int, Int, Int) => T): Array[Array[Array[T]]] = |
|||
tabulate(n1)(i1 => tabulate(n2, n3)(f(i1, _, _))) |
|||
|
|||
/** Returns a four-dimensional array containing values of a given function |
|||
* over ranges of integer values starting from `0`. |
|||
* |
|||
* @param n1 the number of elements in the 1st dimension |
|||
* @param n2 the number of elements in the 2nd dimension |
|||
* @param n3 the number of elements in the 3rd dimension |
|||
* @param n4 the number of elements in the 4th dimension |
|||
* @param f The function computing element values |
|||
*/ |
|||
def tabulate[T: ClassTag](n1: Int, n2: Int, n3: Int, n4: Int)(f: (Int, Int, Int, Int) => T): Array[Array[Array[Array[T]]]] = |
|||
tabulate(n1)(i1 => tabulate(n2, n3, n4)(f(i1, _, _, _))) |
|||
|
|||
/** Returns a five-dimensional array containing values of a given function |
|||
* over ranges of integer values starting from `0`. |
|||
* |
|||
* @param n1 the number of elements in the 1st dimension |
|||
* @param n2 the number of elements in the 2nd dimension |
|||
* @param n3 the number of elements in the 3rd dimension |
|||
* @param n4 the number of elements in the 4th dimension |
|||
* @param n5 the number of elements in the 5th dimension |
|||
* @param f The function computing element values |
|||
*/ |
|||
def tabulate[T: ClassTag](n1: Int, n2: Int, n3: Int, n4: Int, n5: Int)(f: (Int, Int, Int, Int, Int) => T): Array[Array[Array[Array[Array[T]]]]] = |
|||
tabulate(n1)(i1 => tabulate(n2, n3, n4, n5)(f(i1, _, _, _, _))) |
|||
|
|||
/** Returns an array containing a sequence of increasing integers in a range. |
|||
* |
|||
* @param start the start value of the array |
|||
* @param end the end value of the array, exclusive (in other words, this is the first value '''not''' returned) |
|||
* @return the array with values in range `start, start + 1, ..., end - 1` |
|||
* up to, but excluding, `end`. |
|||
*/ |
|||
def range(start: Int, end: Int): Array[Int] = range(start, end, 1) |
|||
|
|||
/** Returns an array containing equally spaced values in some integer interval. |
|||
* |
|||
* @param start the start value of the array |
|||
* @param end the end value of the array, exclusive (in other words, this is the first value '''not''' returned) |
|||
* @param step the increment value of the array (may not be zero) |
|||
* @return the array with values in `start, start + step, ...` up to, but excluding `end` |
|||
*/ |
|||
def range(start: Int, end: Int, step: Int): Array[Int] = { |
|||
if (step == 0) throw new IllegalArgumentException("zero step") |
|||
val b = newBuilder[Int] |
|||
b.sizeHint(immutable.Range.count(start, end, step, isInclusive = false)) |
|||
|
|||
var i = start |
|||
while (if (step < 0) end < i else i < end) { |
|||
b += i |
|||
i += step |
|||
} |
|||
b.result() |
|||
} |
|||
|
|||
/** Returns an array containing repeated applications of a function to a start value. |
|||
* |
|||
* @param start the start value of the array |
|||
* @param len the number of elements returned by the array |
|||
* @param f the function that is repeatedly applied |
|||
* @return the array returning `len` values in the sequence `start, f(start), f(f(start)), ...` |
|||
*/ |
|||
def iterate[T: ClassTag](start: T, len: Int)(f: T => T): Array[T] = { |
|||
val b = newBuilder[T] |
|||
|
|||
if (len > 0) { |
|||
b.sizeHint(len) |
|||
var acc = start |
|||
var i = 1 |
|||
b += acc |
|||
|
|||
while (i < len) { |
|||
acc = f(acc) |
|||
i += 1 |
|||
b += acc |
|||
} |
|||
} |
|||
b.result() |
|||
} |
|||
|
|||
/** Called in a pattern match like `{ case Array(x,y,z) => println('3 elements')}`. |
|||
* |
|||
* @param x the selector value |
|||
* @return sequence wrapped in a [[scala.Some]], if `x` is a Seq, otherwise `None` |
|||
*/ |
|||
def unapplySeq[T](x: Array[T]): Option[IndexedSeq[T]] = |
|||
if (x == null) None else Some(x.toIndexedSeq) |
|||
// !!! the null check should to be necessary, but without it 2241 fails. Seems to be a bug |
|||
// in pattern matcher. @PP: I noted in #4364 I think the behavior is correct. |
|||
} |
|||
|
|||
/** Arrays are mutable, indexed collections of values. `Array[T]` is Scala's representation |
|||
* for Java's `T[]`. |
|||
* |
|||
* {{{ |
|||
* val numbers = Array(1, 2, 3, 4) |
|||
* val first = numbers(0) // read the first element |
|||
* numbers(3) = 100 // replace the 4th array element with 100 |
|||
* val biggerNumbers = numbers.map(_ * 2) // multiply all numbers by two |
|||
* }}} |
|||
* |
|||
* Arrays make use of two common pieces of Scala syntactic sugar, shown on lines 2 and 3 of the above |
|||
* example code. |
|||
* Line 2 is translated into a call to `apply(Int)`, while line 3 is translated into a call to |
|||
* `update(Int, T)`. |
|||
* |
|||
* Two implicit conversions exist in [[scala.Predef]] that are frequently applied to arrays: a conversion |
|||
* to [[scala.collection.mutable.ArrayOps]] (shown on line 4 of the example above) and a conversion |
|||
* to [[scala.collection.mutable.WrappedArray]] (a subtype of [[scala.collection.Seq]]). |
|||
* Both types make available many of the standard operations found in the Scala collections API. |
|||
* The conversion to `ArrayOps` is temporary, as all operations defined on `ArrayOps` return an `Array`, |
|||
* while the conversion to `WrappedArray` is permanent as all operations return a `WrappedArray`. |
|||
* |
|||
* The conversion to `ArrayOps` takes priority over the conversion to `WrappedArray`. For instance, |
|||
* consider the following code: |
|||
* |
|||
* {{{ |
|||
* val arr = Array(1, 2, 3) |
|||
* val arrReversed = arr.reverse |
|||
* val seqReversed : Seq[Int] = arr.reverse |
|||
* }}} |
|||
* |
|||
* Value `arrReversed` will be of type `Array[Int]`, with an implicit conversion to `ArrayOps` occurring |
|||
* to perform the `reverse` operation. The value of `seqReversed`, on the other hand, will be computed |
|||
* by converting to `WrappedArray` first and invoking the variant of `reverse` that returns another |
|||
* `WrappedArray`. |
|||
* |
|||
* @author Martin Odersky |
|||
* @since 1.0 |
|||
* @see [[http://www.scala-lang.org/files/archive/spec/2.12/ Scala Language Specification]], for in-depth information on the transformations the Scala compiler makes on Arrays (Sections 6.6 and 6.15 respectively.) |
|||
* @see [[http://docs.scala-lang.org/sips/completed/scala-2-8-arrays.html "Scala 2.8 Arrays"]] the Scala Improvement Document detailing arrays since Scala 2.8. |
|||
* @see [[http://docs.scala-lang.org/overviews/collections/arrays.html "The Scala 2.8 Collections' API"]] section on `Array` by Martin Odersky for more information. |
|||
* @hideImplicitConversion scala.Predef.booleanArrayOps |
|||
* @hideImplicitConversion scala.Predef.byteArrayOps |
|||
* @hideImplicitConversion scala.Predef.charArrayOps |
|||
* @hideImplicitConversion scala.Predef.doubleArrayOps |
|||
* @hideImplicitConversion scala.Predef.floatArrayOps |
|||
* @hideImplicitConversion scala.Predef.intArrayOps |
|||
* @hideImplicitConversion scala.Predef.longArrayOps |
|||
* @hideImplicitConversion scala.Predef.refArrayOps |
|||
* @hideImplicitConversion scala.Predef.shortArrayOps |
|||
* @hideImplicitConversion scala.Predef.unitArrayOps |
|||
* @hideImplicitConversion scala.LowPriorityImplicits.wrapRefArray |
|||
* @hideImplicitConversion scala.LowPriorityImplicits.wrapIntArray |
|||
* @hideImplicitConversion scala.LowPriorityImplicits.wrapDoubleArray |
|||
* @hideImplicitConversion scala.LowPriorityImplicits.wrapLongArray |
|||
* @hideImplicitConversion scala.LowPriorityImplicits.wrapFloatArray |
|||
* @hideImplicitConversion scala.LowPriorityImplicits.wrapCharArray |
|||
* @hideImplicitConversion scala.LowPriorityImplicits.wrapByteArray |
|||
* @hideImplicitConversion scala.LowPriorityImplicits.wrapShortArray |
|||
* @hideImplicitConversion scala.LowPriorityImplicits.wrapBooleanArray |
|||
* @hideImplicitConversion scala.LowPriorityImplicits.wrapUnitArray |
|||
* @hideImplicitConversion scala.LowPriorityImplicits.genericWrapArray |
|||
* @define coll array |
|||
* @define Coll `Array` |
|||
* @define orderDependent |
|||
* @define orderDependentFold |
|||
* @define mayNotTerminateInf |
|||
* @define willNotTerminateInf |
|||
* @define collectExample |
|||
* @define undefinedorder |
|||
* @define thatinfo the class of the returned collection. In the standard library configuration, |
|||
* `That` is either `Array[B]` if an ClassTag is available for B or `ArraySeq[B]` otherwise. |
|||
* @define zipthatinfo $thatinfo |
|||
* @define bfinfo an implicit value of class `CanBuildFrom` which determines the result class `That` from the current |
|||
* representation type `Repr` and the new element type `B`. |
|||
*/ |
|||
final class Array[T](_length: Int) extends java.io.Serializable with java.lang.Cloneable { |
|||
|
|||
/** The length of the array */ |
|||
def length: Int = throw new Error() |
|||
|
|||
/** The element at given index. |
|||
* |
|||
* Indices start at `0`; `xs.apply(0)` is the first element of array `xs`. |
|||
* Note the indexing syntax `xs(i)` is a shorthand for `xs.apply(i)`. |
|||
* |
|||
* @param i the index |
|||
* @return the element at the given index |
|||
* @throws ArrayIndexOutOfBoundsException if `i < 0` or `length <= i` |
|||
*/ |
|||
def apply(i: Int): T = throw new Error() |
|||
|
|||
/** Update the element at given index. |
|||
* |
|||
* Indices start at `0`; `xs.update(i, x)` replaces the i^th^ element in the array. |
|||
* Note the syntax `xs(i) = x` is a shorthand for `xs.update(i, x)`. |
|||
* |
|||
* @param i the index |
|||
* @param x the value to be written at index `i` |
|||
* @throws ArrayIndexOutOfBoundsException if `i < 0` or `length <= i` |
|||
*/ |
|||
def update(i: Int, x: T) { throw new Error() } |
|||
|
|||
/** Clone the Array. |
|||
* |
|||
* @return A clone of the Array. |
|||
*/ |
|||
override def clone(): Array[T] = throw new Error() |
|||
} |
@ -0,0 +1,325 @@ |
|||
/* |
|||
* Scala (https://www.scala-lang.org) |
|||
* |
|||
* Copyright EPFL and Lightbend, Inc. |
|||
* |
|||
* Licensed under Apache License 2.0 |
|||
* (http://www.apache.org/licenses/LICENSE-2.0). |
|||
* |
|||
* See the NOTICE file distributed with this work for |
|||
* additional information regarding copyright ownership. |
|||
*/ |
|||
|
|||
package scala |
|||
package collection |
|||
|
|||
import scala.annotation.tailrec |
|||
|
|||
/** A template trait for linear sequences of type `LinearSeq[A]` which optimizes |
|||
* the implementation of various methods under the assumption of fast linear access. |
|||
* |
|||
* $linearSeqOptim |
|||
* |
|||
* @define linearSeqOptim |
|||
* Linear-optimized sequences implement most operations in in terms of three methods, |
|||
* which are assumed to have efficient implementations. These are: |
|||
* {{{ |
|||
* def isEmpty: Boolean |
|||
* def head: A |
|||
* def tail: Repr |
|||
* }}} |
|||
* Here, `A` is the type of the sequence elements and `Repr` is the type of the sequence itself. |
|||
* Note that default implementations are provided via inheritance, but these |
|||
* should be overridden for performance. |
|||
* |
|||
* |
|||
*/ |
|||
trait LinearSeqOptimized[+A, +Repr <: LinearSeqOptimized[A, Repr]] extends LinearSeqLike[A, Repr] { self: Repr => |
|||
|
|||
def isEmpty: Boolean |
|||
|
|||
def head: A |
|||
|
|||
def tail: Repr |
|||
|
|||
/** The length of the $coll. |
|||
* |
|||
* $willNotTerminateInf |
|||
* |
|||
* Note: the execution of `length` may take time proportional to the length of the sequence. |
|||
*/ |
|||
def length: Int = { |
|||
var these = self |
|||
var len = 0 |
|||
while (!these.isEmpty) { |
|||
len += 1 |
|||
these = these.tail |
|||
} |
|||
len |
|||
} |
|||
|
|||
/** Selects an element by its index in the $coll. |
|||
* Note: the execution of `apply` may take time proportional to the index value. |
|||
* @throws IndexOutOfBoundsException if `idx` does not satisfy `0 <= idx < length`. |
|||
*/ |
|||
def apply(n: Int): A = { |
|||
val rest = drop(n) |
|||
if (n < 0 || rest.isEmpty) throw new IndexOutOfBoundsException("" + n) |
|||
rest.head |
|||
} |
|||
|
|||
override /*IterableLike*/ |
|||
def foreach[U](f: A => U) { |
|||
var these = this |
|||
while (!these.isEmpty) { |
|||
f(these.head) |
|||
these = these.tail |
|||
} |
|||
} |
|||
|
|||
|
|||
override /*IterableLike*/ |
|||
def forall(p: A => Boolean): Boolean = { |
|||
var these = this |
|||
while (!these.isEmpty) { |
|||
if (!p(these.head)) return false |
|||
these = these.tail |
|||
} |
|||
true |
|||
} |
|||
|
|||
override /*IterableLike*/ |
|||
def exists(p: A => Boolean): Boolean = { |
|||
var these = this |
|||
while (!these.isEmpty) { |
|||
if (p(these.head)) return true |
|||
these = these.tail |
|||
} |
|||
false |
|||
} |
|||
|
|||
override /*SeqLike*/ |
|||
def contains[A1 >: A](elem: A1): Boolean = { |
|||
var these = this |
|||
while (!these.isEmpty) { |
|||
if (these.head == elem) return true |
|||
these = these.tail |
|||
} |
|||
false |
|||
} |
|||
|
|||
override /*IterableLike*/ |
|||
def find(p: A => Boolean): Option[A] = { |
|||
var these = this |
|||
while (!these.isEmpty) { |
|||
if (p(these.head)) return Some(these.head) |
|||
these = these.tail |
|||
} |
|||
None |
|||
} |
|||
|
|||
override /*TraversableLike*/ |
|||
def foldLeft[B](z: B)(@deprecatedName('f) op: (B, A) => B): B = { |
|||
var acc = z |
|||
var these = this |
|||
while (!these.isEmpty) { |
|||
acc = op(acc, these.head) |
|||
these = these.tail |
|||
} |
|||
acc |
|||
} |
|||
|
|||
override /*IterableLike*/ |
|||
def foldRight[B](z: B)(@deprecatedName('f) op: (A, B) => B): B = |
|||
if (this.isEmpty) z |
|||
else op(head, tail.foldRight(z)(op)) |
|||
|
|||
override /*TraversableLike*/ |
|||
def reduceLeft[B >: A](@deprecatedName('f) op: (B, A) => B): B = |
|||
if (isEmpty) throw new UnsupportedOperationException("empty.reduceLeft") |
|||
else tail.foldLeft[B](head)(op) |
|||
|
|||
override /*IterableLike*/ |
|||
def reduceRight[B >: A](op: (A, B) => B): B = |
|||
if (isEmpty) throw new UnsupportedOperationException("Nil.reduceRight") |
|||
else if (tail.isEmpty) head |
|||
else op(head, tail.reduceRight(op)) |
|||
|
|||
override /*TraversableLike*/ |
|||
def last: A = { |
|||
if (isEmpty) throw new NoSuchElementException |
|||
var these = this |
|||
var nx = these.tail |
|||
while (!nx.isEmpty) { |
|||
these = nx |
|||
nx = nx.tail |
|||
} |
|||
these.head |
|||
} |
|||
|
|||
override /*IterableLike*/ |
|||
def take(n: Int): Repr = { |
|||
val b = newBuilder |
|||
var i = 0 |
|||
var these = repr |
|||
while (!these.isEmpty && i < n) { |
|||
i += 1 |
|||
b += these.head |
|||
these = these.tail |
|||
} |
|||
b.result() |
|||
} |
|||
|
|||
override /*TraversableLike*/ |
|||
def drop(n: Int): Repr = { |
|||
var these: Repr = repr |
|||
var count = n |
|||
while (!these.isEmpty && count > 0) { |
|||
these = these.tail |
|||
count -= 1 |
|||
} |
|||
// !!! This line should actually be something like: |
|||
// newBuilder ++= these result |
|||
// since we are in collection.*, not immutable.*. |
|||
// However making that change will pessimize all the |
|||
// immutable linear seqs (like list) which surely expect |
|||
// drop to share. (Or at least it would penalize List if |
|||
// it didn't override drop. It would be a lot better if |
|||
// the leaf collections didn't override so many methods.) |
|||
// |
|||
// Upshot: MutableList is broken and passes part of the |
|||
// original list as the result of drop. |
|||
these |
|||
} |
|||
|
|||
override /*IterableLike*/ |
|||
def dropRight(n: Int): Repr = { |
|||
val b = newBuilder |
|||
var these = this |
|||
var lead = this drop n |
|||
while (!lead.isEmpty) { |
|||
b += these.head |
|||
these = these.tail |
|||
lead = lead.tail |
|||
} |
|||
b.result() |
|||
} |
|||
|
|||
override /*IterableLike*/ |
|||
def slice(from: Int, until: Int): Repr = { |
|||
var these: Repr = repr |
|||
var count = from max 0 |
|||
if (until <= count) |
|||
return newBuilder.result() |
|||
|
|||
val b = newBuilder |
|||
var sliceElems = until - count |
|||
while (these.nonEmpty && count > 0) { |
|||
these = these.tail |
|||
count -= 1 |
|||
} |
|||
while (these.nonEmpty && sliceElems > 0) { |
|||
sliceElems -= 1 |
|||
b += these.head |
|||
these = these.tail |
|||
} |
|||
b.result() |
|||
} |
|||
|
|||
override /*IterableLike*/ |
|||
def takeWhile(p: A => Boolean): Repr = { |
|||
val b = newBuilder |
|||
var these = this |
|||
while (!these.isEmpty && p(these.head)) { |
|||
b += these.head |
|||
these = these.tail |
|||
} |
|||
b.result() |
|||
} |
|||
|
|||
override /*TraversableLike*/ |
|||
def span(p: A => Boolean): (Repr, Repr) = { |
|||
var these: Repr = repr |
|||
val b = newBuilder |
|||
while (!these.isEmpty && p(these.head)) { |
|||
b += these.head |
|||
these = these.tail |
|||
} |
|||
(b.result(), these) |
|||
} |
|||
|
|||
override /*IterableLike*/ |
|||
def sameElements[B >: A](that: GenIterable[B]): Boolean = that match { |
|||
case that1: LinearSeq[_] => |
|||
// Probably immutable, so check reference identity first (it's quick anyway) |
|||
(this eq that1) || { |
|||
var these = this |
|||
var those = that1 |
|||
while (!these.isEmpty && !those.isEmpty && these.head == those.head) { |
|||
these = these.tail |
|||
those = those.tail |
|||
} |
|||
these.isEmpty && those.isEmpty |
|||
} |
|||
case _ => |
|||
super.sameElements(that) |
|||
} |
|||
|
|||
override /*SeqLike*/ |
|||
def lengthCompare(len: Int): Int = { |
|||
@tailrec def loop(i: Int, xs: Repr): Int = { |
|||
if (i == len) |
|||
if (xs.isEmpty) 0 else 1 |
|||
else if (xs.isEmpty) |
|||
-1 |
|||
else |
|||
loop(i + 1, xs.tail) |
|||
} |
|||
if (len < 0) 1 |
|||
else loop(0, this) |
|||
} |
|||
|
|||
override /*SeqLike*/ |
|||
def isDefinedAt(x: Int): Boolean = x >= 0 && lengthCompare(x) > 0 |
|||
|
|||
override /*SeqLike*/ |
|||
def segmentLength(p: A => Boolean, from: Int): Int = { |
|||
var i = 0 |
|||
var these = this drop from |
|||
while (!these.isEmpty && p(these.head)) { |
|||
i += 1 |
|||
these = these.tail |
|||
} |
|||
i |
|||
} |
|||
|
|||
override /*SeqLike*/ |
|||
def indexWhere(p: A => Boolean, from: Int): Int = { |
|||
var i = math.max(from, 0) |
|||
var these = this drop from |
|||
while (these.nonEmpty) { |
|||
if (p(these.head)) |
|||
return i |
|||
|
|||
i += 1 |
|||
these = these.tail |
|||
} |
|||
-1 |
|||
} |
|||
|
|||
override /*SeqLike*/ |
|||
def lastIndexWhere(p: A => Boolean, end: Int): Int = { |
|||
var i = 0 |
|||
var these = this |
|||
var last = -1 |
|||
while (!these.isEmpty && i <= end) { |
|||
if (p(these.head)) last = i |
|||
these = these.tail |
|||
i += 1 |
|||
} |
|||
last |
|||
} |
|||
|
|||
override /*TraversableLike*/ |
|||
def tails: Iterator[Repr] = Iterator.iterate(repr)(_.tail).takeWhile(_.nonEmpty) ++ Iterator(newBuilder.result) |
|||
} |
@ -0,0 +1,375 @@ |
|||
/* |
|||
* Scala (https://www.scala-lang.org) |
|||
* |
|||
* Copyright EPFL and Lightbend, Inc. |
|||
* |
|||
* Licensed under Apache License 2.0 |
|||
* (http://www.apache.org/licenses/LICENSE-2.0). |
|||
* |
|||
* See the NOTICE file distributed with this work for |
|||
* additional information regarding copyright ownership. |
|||
*/ |
|||
|
|||
package scala |
|||
package io |
|||
|
|||
import scala.collection.AbstractIterator |
|||
import java.io.{ FileInputStream, InputStream, PrintStream, File => JFile, Closeable } |
|||
import java.net.{ URI, URL } |
|||
|
|||
/** This object provides convenience methods to create an iterable |
|||
* representation of a source file. |
|||
* |
|||
* @author Burak Emir, Paul Phillips |
|||
*/ |
|||
object Source { |
|||
val DefaultBufSize = 2048 |
|||
|
|||
/** Creates a `Source` from System.in. |
|||
*/ |
|||
def stdin = fromInputStream(System.in) |
|||
|
|||
/** Creates a Source from an Iterable. |
|||
* |
|||
* @param iterable the Iterable |
|||
* @return the Source |
|||
*/ |
|||
def fromIterable(iterable: Iterable[Char]): Source = new Source { |
|||
val iter = iterable.iterator |
|||
} withReset(() => fromIterable(iterable)) |
|||
|
|||
/** Creates a Source instance from a single character. |
|||
*/ |
|||
def fromChar(c: Char): Source = fromIterable(Array(c)) |
|||
|
|||
/** creates Source from array of characters, with empty description. |
|||
*/ |
|||
def fromChars(chars: Array[Char]): Source = fromIterable(chars) |
|||
|
|||
/** creates Source from a String, with no description. |
|||
*/ |
|||
def fromString(s: String): Source = fromIterable(s) |
|||
|
|||
/** creates Source from file with given name, setting its description to |
|||
* filename. |
|||
*/ |
|||
def fromFile(name: String)(implicit codec: Codec): BufferedSource = |
|||
fromFile(new JFile(name))(codec) |
|||
|
|||
/** creates Source from file with given name, using given encoding, setting |
|||
* its description to filename. |
|||
*/ |
|||
def fromFile(name: String, enc: String): BufferedSource = |
|||
fromFile(name)(Codec(enc)) |
|||
|
|||
/** creates `source` from file with given file `URI`. |
|||
*/ |
|||
def fromFile(uri: URI)(implicit codec: Codec): BufferedSource = |
|||
fromFile(new JFile(uri))(codec) |
|||
|
|||
/** creates Source from file with given file: URI |
|||
*/ |
|||
def fromFile(uri: URI, enc: String): BufferedSource = |
|||
fromFile(uri)(Codec(enc)) |
|||
|
|||
/** creates Source from file, using default character encoding, setting its |
|||
* description to filename. |
|||
*/ |
|||
def fromFile(file: JFile)(implicit codec: Codec): BufferedSource = |
|||
fromFile(file, Source.DefaultBufSize)(codec) |
|||
|
|||
/** same as fromFile(file, enc, Source.DefaultBufSize) |
|||
*/ |
|||
def fromFile(file: JFile, enc: String): BufferedSource = |
|||
fromFile(file)(Codec(enc)) |
|||
|
|||
def fromFile(file: JFile, enc: String, bufferSize: Int): BufferedSource = |
|||
fromFile(file, bufferSize)(Codec(enc)) |
|||
|
|||
/** Creates Source from `file`, using given character encoding, setting |
|||
* its description to filename. Input is buffered in a buffer of size |
|||
* `bufferSize`. |
|||
*/ |
|||
def fromFile(file: JFile, bufferSize: Int)(implicit codec: Codec): BufferedSource = { |
|||
val inputStream = new FileInputStream(file) |
|||
|
|||
createBufferedSource( |
|||
inputStream, |
|||
bufferSize, |
|||
() => fromFile(file, bufferSize)(codec), |
|||
() => inputStream.close() |
|||
)(codec) withDescription ("file:" + file.getAbsolutePath) |
|||
} |
|||
|
|||
/** Create a `Source` from array of bytes, decoding |
|||
* the bytes according to codec. |
|||
* |
|||
* @return the created `Source` instance. |
|||
*/ |
|||
def fromBytes(bytes: Array[Byte])(implicit codec: Codec): Source = |
|||
fromString(new String(bytes, codec.name)) |
|||
|
|||
def fromBytes(bytes: Array[Byte], enc: String): Source = |
|||
fromBytes(bytes)(Codec(enc)) |
|||
|
|||
/** Create a `Source` from array of bytes, assuming |
|||
* one byte per character (ISO-8859-1 encoding.) |
|||
*/ |
|||
def fromRawBytes(bytes: Array[Byte]): Source = |
|||
fromString(new String(bytes, Codec.ISO8859.name)) |
|||
|
|||
/** creates `Source` from file with given file: URI |
|||
*/ |
|||
def fromURI(uri: URI)(implicit codec: Codec): BufferedSource = |
|||
fromFile(new JFile(uri))(codec) |
|||
|
|||
/** same as fromURL(new URL(s))(Codec(enc)) |
|||
*/ |
|||
def fromURL(s: String, enc: String): BufferedSource = |
|||
fromURL(s)(Codec(enc)) |
|||
|
|||
/** same as fromURL(new URL(s)) |
|||
*/ |
|||
def fromURL(s: String)(implicit codec: Codec): BufferedSource = |
|||
fromURL(new URL(s))(codec) |
|||
|
|||
/** same as fromInputStream(url.openStream())(Codec(enc)) |
|||
*/ |
|||
def fromURL(url: URL, enc: String): BufferedSource = |
|||
fromURL(url)(Codec(enc)) |
|||
|
|||
/** same as fromInputStream(url.openStream())(codec) |
|||
*/ |
|||
def fromURL(url: URL)(implicit codec: Codec): BufferedSource = |
|||
fromInputStream(url.openStream())(codec) |
|||
|
|||
/** Reads data from inputStream with a buffered reader, using the encoding |
|||
* in implicit parameter codec. |
|||
* |
|||
* @param inputStream the input stream from which to read |
|||
* @param bufferSize buffer size (defaults to Source.DefaultBufSize) |
|||
* @param reset a () => Source which resets the stream (if unset, reset() will throw an Exception) |
|||
* @param close a () => Unit method which closes the stream (if unset, close() will do nothing) |
|||
* @param codec (implicit) a scala.io.Codec specifying behavior (defaults to Codec.default) |
|||
* @return the buffered source |
|||
*/ |
|||
def createBufferedSource( |
|||
inputStream: InputStream, |
|||
bufferSize: Int = DefaultBufSize, |
|||
reset: () => Source = null, |
|||
close: () => Unit = null |
|||
)(implicit codec: Codec): BufferedSource = { |
|||
// workaround for default arguments being unable to refer to other parameters |
|||
val resetFn = if (reset == null) () => createBufferedSource(inputStream, bufferSize, reset, close)(codec) else reset |
|||
|
|||
new BufferedSource(inputStream, bufferSize)(codec) withReset resetFn withClose close |
|||
} |
|||
|
|||
def fromInputStream(is: InputStream, enc: String): BufferedSource = |
|||
fromInputStream(is)(Codec(enc)) |
|||
|
|||
def fromInputStream(is: InputStream)(implicit codec: Codec): BufferedSource = |
|||
createBufferedSource(is, reset = () => fromInputStream(is)(codec), close = () => is.close())(codec) |
|||
|
|||
/** Reads data from a classpath resource, using either a context classloader (default) or a passed one. |
|||
* |
|||
* @param resource name of the resource to load from the classpath |
|||
* @param classLoader classloader to be used, or context classloader if not specified |
|||
* @return the buffered source |
|||
*/ |
|||
def fromResource(resource: String, classLoader: ClassLoader = Thread.currentThread().getContextClassLoader())(implicit codec: Codec): BufferedSource = |
|||
fromInputStream(classLoader.getResourceAsStream(resource)) |
|||
|
|||
} |
|||
|
|||
/** An iterable representation of source data. |
|||
* It may be reset with the optional [[reset]] method. |
|||
* |
|||
* Subclasses must supply [[scala.io.Source.iter the underlying iterator]]. |
|||
* |
|||
* Error handling may be customized by overriding the [[scala.io.Source.report report]] method. |
|||
* |
|||
* The [[scala.io.Source.ch current input]] and [[scala.io.Source.pos position]], |
|||
* as well as the [[scala.io.Source.next next character]] methods delegate to |
|||
* [[scala.io.Source#Positioner the positioner]]. |
|||
* |
|||
* The default positioner encodes line and column numbers in the position passed to [[report]]. |
|||
* This behavior can be changed by supplying a |
|||
* [[scala.io.Source.withPositioning(pos:* custom positioner]]. |
|||
* |
|||
*/ |
|||
abstract class Source extends Iterator[Char] with Closeable { |
|||
/** the actual iterator */ |
|||
protected val iter: Iterator[Char] |
|||
|
|||
// ------ public values |
|||
|
|||
/** description of this source, default empty */ |
|||
var descr: String = "" |
|||
var nerrors = 0 |
|||
var nwarnings = 0 |
|||
|
|||
private def lineNum(line: Int): String = (getLines() drop (line - 1) take 1).mkString |
|||
|
|||
class LineIterator extends AbstractIterator[String] with Iterator[String] { |
|||
private[this] val sb = new StringBuilder |
|||
|
|||
lazy val iter: BufferedIterator[Char] = Source.this.iter.buffered |
|||
def isNewline(ch: Char) = ch == '\r' || ch == '\n' |
|||
def getc() = iter.hasNext && { |
|||
val ch = iter.next() |
|||
if (ch == '\n') false |
|||
else if (ch == '\r') { |
|||
if (iter.hasNext && iter.head == '\n') |
|||
iter.next() |
|||
|
|||
false |
|||
} |
|||
else { |
|||
sb append ch |
|||
true |
|||
} |
|||
} |
|||
def hasNext = iter.hasNext |
|||
def next = { |
|||
sb.clear() |
|||
while (getc()) { } |
|||
sb.toString |
|||
} |
|||
} |
|||
|
|||
/** Returns an iterator who returns lines (NOT including newline character(s)). |
|||
* It will treat any of \r\n, \r, or \n as a line separator (longest match) - if |
|||
* you need more refined behavior you can subclass Source#LineIterator directly. |
|||
*/ |
|||
def getLines(): Iterator[String] = new LineIterator() |
|||
|
|||
/** Returns `'''true'''` if this source has more characters. |
|||
*/ |
|||
def hasNext = iter.hasNext |
|||
|
|||
/** Returns next character. |
|||
*/ |
|||
def next(): Char = positioner.next() |
|||
|
|||
class Positioner(encoder: Position) { |
|||
def this() = this(RelaxedPosition) |
|||
/** the last character returned by next. */ |
|||
var ch: Char = _ |
|||
|
|||
/** position of last character returned by next */ |
|||
var pos = 0 |
|||
|
|||
/** current line and column */ |
|||
var cline = 1 |
|||
var ccol = 1 |
|||
|
|||
/** default col increment for tabs '\t', set to 4 initially */ |
|||
var tabinc = 4 |
|||
|
|||
def next(): Char = { |
|||
ch = iter.next() |
|||
pos = encoder.encode(cline, ccol) |
|||
ch match { |
|||
case '\n' => |
|||
ccol = 1 |
|||
cline += 1 |
|||
case '\t' => |
|||
ccol += tabinc |
|||
case _ => |
|||
ccol += 1 |
|||
} |
|||
ch |
|||
} |
|||
} |
|||
/** A Position implementation which ignores errors in |
|||
* the positions. |
|||
*/ |
|||
object RelaxedPosition extends Position { |
|||
def checkInput(line: Int, column: Int): Unit = () |
|||
} |
|||
object RelaxedPositioner extends Positioner(RelaxedPosition) { } |
|||
object NoPositioner extends Positioner(Position) { |
|||
override def next(): Char = iter.next() |
|||
} |
|||
def ch = positioner.ch |
|||
def pos = positioner.pos |
|||
|
|||
/** Reports an error message to the output stream `out`. |
|||
* |
|||
* @param pos the source position (line/column) |
|||
* @param msg the error message to report |
|||
* @param out PrintStream to use (optional: defaults to `Console.err`) |
|||
*/ |
|||
def reportError( |
|||
pos: Int, |
|||
msg: String, |
|||
out: PrintStream = Console.err) |
|||
{ |
|||
nerrors += 1 |
|||
report(pos, msg, out) |
|||
} |
|||
|
|||
private def spaces(n: Int) = List.fill(n)(' ').mkString |
|||
/** |
|||
* @param pos the source position (line/column) |
|||
* @param msg the error message to report |
|||
* @param out PrintStream to use |
|||
*/ |
|||
def report(pos: Int, msg: String, out: PrintStream) { |
|||
val line = Position line pos |
|||
val col = Position column pos |
|||
|
|||
out println "%s:%d:%d: %s%s%s^".format(descr, line, col, msg, lineNum(line), spaces(col - 1)) |
|||
} |
|||
|
|||
/** |
|||
* @param pos the source position (line/column) |
|||
* @param msg the warning message to report |
|||
* @param out PrintStream to use (optional: defaults to `Console.out`) |
|||
*/ |
|||
def reportWarning( |
|||
pos: Int, |
|||
msg: String, |
|||
out: PrintStream = Console.out) |
|||
{ |
|||
nwarnings += 1 |
|||
report(pos, "warning! " + msg, out) |
|||
} |
|||
|
|||
private[this] var resetFunction: () => Source = null |
|||
private[this] var closeFunction: () => Unit = null |
|||
private[this] var positioner: Positioner = RelaxedPositioner |
|||
|
|||
def withReset(f: () => Source): this.type = { |
|||
resetFunction = f |
|||
this |
|||
} |
|||
def withClose(f: () => Unit): this.type = { |
|||
closeFunction = f |
|||
this |
|||
} |
|||
def withDescription(text: String): this.type = { |
|||
descr = text |
|||
this |
|||
} |
|||
/** Change or disable the positioner. */ |
|||
def withPositioning(on: Boolean): this.type = { |
|||
positioner = if (on) RelaxedPositioner else NoPositioner |
|||
this |
|||
} |
|||
def withPositioning(pos: Positioner): this.type = { |
|||
positioner = pos |
|||
this |
|||
} |
|||
|
|||
/** The close() method closes the underlying resource. */ |
|||
def close() { |
|||
if (closeFunction != null) closeFunction() |
|||
} |
|||
|
|||
/** The reset() method creates a fresh copy of this Source. */ |
|||
def reset(): Source = |
|||
if (resetFunction != null) resetFunction() |
|||
else throw new UnsupportedOperationException("Source's reset() method was not set.") |
|||
} |
@ -0,0 +1,98 @@ |
|||
/* |
|||
* Scala (https://www.scala-lang.org) |
|||
* |
|||
* Copyright EPFL and Lightbend, Inc. |
|||
* |
|||
* Licensed under Apache License 2.0 |
|||
* (http://www.apache.org/licenses/LICENSE-2.0). |
|||
* |
|||
* See the NOTICE file distributed with this work for |
|||
* additional information regarding copyright ownership. |
|||
*/ |
|||
|
|||
package scala |
|||
package util.control |
|||
|
|||
/** A class that can be instantiated for the break control abstraction. |
|||
* Example usage: |
|||
* {{{ |
|||
* val mybreaks = new Breaks |
|||
* import mybreaks.{break, breakable} |
|||
* |
|||
* breakable { |
|||
* for (...) { |
|||
* if (...) break() |
|||
* } |
|||
* } |
|||
* }}} |
|||
* Calls to break from one instantiation of `Breaks` will never |
|||
* target breakable objects of some other instantiation. |
|||
*/ |
|||
class Breaks { |
|||
|
|||
private val breakException = new BreakControl |
|||
|
|||
/** |
|||
* A block from which one can exit with a `break`. The `break` may be |
|||
* executed further down in the call stack provided that it is called on the |
|||
* exact same instance of `Breaks`. |
|||
*/ |
|||
def breakable(op: => Unit) { |
|||
try { |
|||
op |
|||
} catch { |
|||
case ex: BreakControl => |
|||
if (ex ne breakException) throw ex |
|||
} |
|||
} |
|||
|
|||
sealed trait TryBlock[T] { |
|||
def catchBreak(onBreak: =>T): T |
|||
} |
|||
|
|||
/** |
|||
* This variant enables the execution of a code block in case of a `break()`: |
|||
* {{{ |
|||
* tryBreakable { |
|||
* for (...) { |
|||
* if (...) break() |
|||
* } |
|||
* } catchBreak { |
|||
* doCleanup() |
|||
* } |
|||
* }}} |
|||
*/ |
|||
def tryBreakable[T](op: =>T) = new TryBlock[T] { |
|||
def catchBreak(onBreak: =>T) = try { |
|||
op |
|||
} catch { |
|||
case ex: BreakControl => |
|||
if (ex ne breakException) throw ex |
|||
onBreak |
|||
} |
|||
} |
|||
|
|||
/** |
|||
* Break from dynamically closest enclosing breakable block using this exact |
|||
* `Breaks` instance. |
|||
* |
|||
* @note This might be different than the statically closest enclosing block! |
|||
*/ |
|||
def break(): Nothing = { throw breakException } |
|||
} |
|||
|
|||
/** An object that can be used for the break control abstraction. |
|||
* Example usage: |
|||
* {{{ |
|||
* import Breaks.{break, breakable} |
|||
* |
|||
* breakable { |
|||
* for (...) { |
|||
* if (...) break |
|||
* } |
|||
* } |
|||
* }}} |
|||
*/ |
|||
object Breaks extends Breaks |
|||
|
|||
private class BreakControl extends ControlThrowable |
@ -0,0 +1,7 @@ |
|||
{ |
|||
// Use IntelliSense to learn about possible attributes. |
|||
// Hover to view descriptions of existing attributes. |
|||
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 |
|||
"version": "0.2.0", |
|||
"configurations": [] |
|||
} |
@ -0,0 +1,5 @@ |
|||
{ |
|||
"files.watcherExclude": { |
|||
"**/target": true |
|||
} |
|||
} |
@ -0,0 +1,16 @@ |
|||
{ |
|||
"semanticDBVersion": "4.4.0", |
|||
"supportedScalaVersions": [ |
|||
"2.13.4", |
|||
"2.12.12", |
|||
"2.12.11", |
|||
"2.12.10", |
|||
"2.13.2", |
|||
"2.13.3", |
|||
"2.11.12", |
|||
"2.12.8", |
|||
"2.12.9", |
|||
"2.13.0", |
|||
"2.13.1" |
|||
] |
|||
} |
@ -0,0 +1,167 @@ |
|||
{ |
|||
"version": "1.4.0", |
|||
"project": { |
|||
"name": "root-04-test", |
|||
"directory": "/Users/hrbrmstr/Development/2020-code-advent/scala/04/04", |
|||
"workspaceDir": "/Users/hrbrmstr/Development/2020-code-advent/scala/04/04", |
|||
"sources": [ |
|||
"/Users/hrbrmstr/Development/2020-code-advent/scala/04/04/src/test/scala", |
|||
"/Users/hrbrmstr/Development/2020-code-advent/scala/04/04/src/test/scala-2.13", |
|||
"/Users/hrbrmstr/Development/2020-code-advent/scala/04/04/src/test/scala-2", |
|||
"/Users/hrbrmstr/Development/2020-code-advent/scala/04/04/src/test/java", |
|||
"/Users/hrbrmstr/Development/2020-code-advent/scala/04/04/target/scala-2.13/src_managed/test" |
|||
], |
|||
"dependencies": [ |
|||
"root-04" |
|||
], |
|||
"classpath": [ |
|||
"/Users/hrbrmstr/Development/2020-code-advent/scala/04/04/.bloop/root-04/scala-2.13/classes", |
|||
"/Users/hrbrmstr/Library/Caches/Coursier/v1/https/repo1.maven.org/maven2/org/scala-lang/scala-library/2.13.3/scala-library-2.13.3.jar", |
|||
"/Users/hrbrmstr/Library/Caches/Coursier/v1/https/repo1.maven.org/maven2/org/scala-lang/modules/scala-parser-combinators_2.13/1.1.2/scala-parser-combinators_2.13-1.1.2.jar" |
|||
], |
|||
"out": "/Users/hrbrmstr/Development/2020-code-advent/scala/04/04/.bloop/root-04", |
|||
"classesDir": "/Users/hrbrmstr/Development/2020-code-advent/scala/04/04/.bloop/root-04/scala-2.13/test-classes", |
|||
"resources": [ |
|||
"/Users/hrbrmstr/Development/2020-code-advent/scala/04/04/src/test/resources", |
|||
"/Users/hrbrmstr/Development/2020-code-advent/scala/04/04/target/scala-2.13/resource_managed/test" |
|||
], |
|||
"scala": { |
|||
"organization": "org.scala-lang", |
|||
"name": "scala-compiler", |
|||
"version": "2.13.3", |
|||
"options": [ |
|||
|
|||
], |
|||
"jars": [ |
|||
"/Users/hrbrmstr/Library/Caches/Coursier/v1/https/repo1.maven.org/maven2/org/scala-lang/scala-compiler/2.13.3/scala-compiler-2.13.3.jar", |
|||
"/Users/hrbrmstr/Library/Caches/Coursier/v1/https/repo1.maven.org/maven2/org/scala-lang/scala-library/2.13.3/scala-library-2.13.3.jar", |
|||
"/Users/hrbrmstr/Library/Caches/Coursier/v1/https/repo1.maven.org/maven2/org/scala-lang/scala-reflect/2.13.3/scala-reflect-2.13.3.jar", |
|||
"/Users/hrbrmstr/Library/Caches/Coursier/v1/https/repo1.maven.org/maven2/org/jline/jline/3.15.0/jline-3.15.0.jar", |
|||
"/Users/hrbrmstr/Library/Caches/Coursier/v1/https/repo1.maven.org/maven2/net/java/dev/jna/jna/5.3.1/jna-5.3.1.jar" |
|||
], |
|||
"analysis": "/Users/hrbrmstr/Development/2020-code-advent/scala/04/04/target/streams/test/bloopAnalysisOut/_global/streams/inc_compile_2.13.zip", |
|||
"setup": { |
|||
"order": "mixed", |
|||
"addLibraryToBootClasspath": true, |
|||
"addCompilerToClasspath": false, |
|||
"addExtraJarsToClasspath": false, |
|||
"manageBootClasspath": true, |
|||
"filterLibraryFromClasspath": true |
|||
} |
|||
}, |
|||
"java": { |
|||
"options": [ |
|||
|
|||
] |
|||
}, |
|||
"test": { |
|||
"frameworks": [ |
|||
{ |
|||
"names": [ |
|||
"org.scalacheck.ScalaCheckFramework" |
|||
] |
|||
}, |
|||
{ |
|||
"names": [ |
|||
"org.specs2.runner.Specs2Framework", |
|||
"org.specs2.runner.SpecsFramework" |
|||
] |
|||
}, |
|||
{ |
|||
"names": [ |
|||
"org.specs.runner.SpecsFramework" |
|||
] |
|||
}, |
|||
{ |
|||
"names": [ |
|||
"org.scalatest.tools.Framework", |
|||
"org.scalatest.tools.ScalaTestFramework" |
|||
] |
|||
}, |
|||
{ |
|||
"names": [ |
|||
"com.novocode.junit.JUnitFramework" |
|||
] |
|||
} |
|||
], |
|||
"options": { |
|||
"excludes": [ |
|||
|
|||
], |
|||
"arguments": [ |
|||
|
|||
] |
|||
} |
|||
}, |
|||
"platform": { |
|||
"name": "jvm", |
|||
"config": { |
|||
"home": "/Library/Java/JavaVirtualMachines/openjdk-11.0.2.jdk/Contents/Home", |
|||
"options": [ |
|||
"-Duser.dir=/Users/hrbrmstr/Development/2020-code-advent/scala/04/04" |
|||
] |
|||
}, |
|||
"mainClass": [ |
|||
|
|||
] |
|||
}, |
|||
"resolution": { |
|||
"modules": [ |
|||
{ |
|||
"organization": "org.scala-lang", |
|||
"name": "scala-library", |
|||
"version": "2.13.3", |
|||
"configurations": "default", |
|||
"artifacts": [ |
|||
{ |
|||
"name": "scala-library", |
|||
"path": "/Users/hrbrmstr/Library/Caches/Coursier/v1/https/repo1.maven.org/maven2/org/scala-lang/scala-library/2.13.3/scala-library-2.13.3.jar" |
|||
}, |
|||
{ |
|||
"name": "scala-library", |
|||
"classifier": "sources", |
|||
"path": "/Users/hrbrmstr/Library/Caches/Coursier/v1/https/repo1.maven.org/maven2/org/scala-lang/scala-library/2.13.3/scala-library-2.13.3-sources.jar" |
|||
} |
|||
] |
|||
}, |
|||
{ |
|||
"organization": "org.scala-lang.modules", |
|||
"name": "scala-parser-combinators_2.13", |
|||
"version": "1.1.2", |
|||
"configurations": "default", |
|||
"artifacts": [ |
|||
{ |
|||
"name": "scala-parser-combinators_2.13", |
|||
"path": "/Users/hrbrmstr/Library/Caches/Coursier/v1/https/repo1.maven.org/maven2/org/scala-lang/modules/scala-parser-combinators_2.13/1.1.2/scala-parser-combinators_2.13-1.1.2.jar" |
|||
}, |
|||
{ |
|||
"name": "scala-parser-combinators_2.13", |
|||
"classifier": "sources", |
|||
"path": "/Users/hrbrmstr/Library/Caches/Coursier/v1/https/repo1.maven.org/maven2/org/scala-lang/modules/scala-parser-combinators_2.13/1.1.2/scala-parser-combinators_2.13-1.1.2-sources.jar" |
|||
} |
|||
] |
|||
}, |
|||
{ |
|||
"organization": "org.scala-lang", |
|||
"name": "scala-library", |
|||
"version": "2.13.3", |
|||
"configurations": "optional", |
|||
"artifacts": [ |
|||
{ |
|||
"name": "scala-library", |
|||
"path": "/Users/hrbrmstr/Library/Caches/Coursier/v1/https/repo1.maven.org/maven2/org/scala-lang/scala-library/2.13.3/scala-library-2.13.3.jar" |
|||
}, |
|||
{ |
|||
"name": "scala-library", |
|||
"classifier": "sources", |
|||
"path": "/Users/hrbrmstr/Library/Caches/Coursier/v1/https/repo1.maven.org/maven2/org/scala-lang/scala-library/2.13.3/scala-library-2.13.3-sources.jar" |
|||
} |
|||
] |
|||
} |
|||
] |
|||
}, |
|||
"tags": [ |
|||
"test" |
|||
] |
|||
} |
|||
} |
@ -0,0 +1,166 @@ |
|||
{ |
|||
"version": "1.4.0", |
|||
"project": { |
|||
"name": "root-04", |
|||
"directory": "/Users/hrbrmstr/Development/2020-code-advent/scala/04/04", |
|||
"workspaceDir": "/Users/hrbrmstr/Development/2020-code-advent/scala/04/04", |
|||
"sources": [ |
|||
"/Users/hrbrmstr/Development/2020-code-advent/scala/04/04/src/main/scala", |
|||
"/Users/hrbrmstr/Development/2020-code-advent/scala/04/04/src/main/scala-2.13", |
|||
"/Users/hrbrmstr/Development/2020-code-advent/scala/04/04/src/main/scala-2", |
|||
"/Users/hrbrmstr/Development/2020-code-advent/scala/04/04/src/main/java", |
|||
"/Users/hrbrmstr/Development/2020-code-advent/scala/04/04/target/scala-2.13/src_managed/main" |
|||
], |
|||
"dependencies": [ |
|||
|
|||
], |
|||
"classpath": [ |
|||
"/Users/hrbrmstr/Library/Caches/Coursier/v1/https/repo1.maven.org/maven2/org/scala-lang/scala-library/2.13.3/scala-library-2.13.3.jar", |
|||
"/Users/hrbrmstr/Library/Caches/Coursier/v1/https/repo1.maven.org/maven2/org/scala-lang/modules/scala-parser-combinators_2.13/1.1.2/scala-parser-combinators_2.13-1.1.2.jar" |
|||
], |
|||
"out": "/Users/hrbrmstr/Development/2020-code-advent/scala/04/04/.bloop/root-04", |
|||
"classesDir": "/Users/hrbrmstr/Development/2020-code-advent/scala/04/04/.bloop/root-04/scala-2.13/classes", |
|||
"resources": [ |
|||
"/Users/hrbrmstr/Development/2020-code-advent/scala/04/04/src/main/resources", |
|||
"/Users/hrbrmstr/Development/2020-code-advent/scala/04/04/target/scala-2.13/resource_managed/main" |
|||
], |
|||
"scala": { |
|||
"organization": "org.scala-lang", |
|||
"name": "scala-compiler", |
|||
"version": "2.13.3", |
|||
"options": [ |
|||
|
|||
], |
|||
"jars": [ |
|||
"/Users/hrbrmstr/Library/Caches/Coursier/v1/https/repo1.maven.org/maven2/org/scala-lang/scala-compiler/2.13.3/scala-compiler-2.13.3.jar", |
|||
"/Users/hrbrmstr/Library/Caches/Coursier/v1/https/repo1.maven.org/maven2/org/scala-lang/scala-library/2.13.3/scala-library-2.13.3.jar", |
|||
"/Users/hrbrmstr/Library/Caches/Coursier/v1/https/repo1.maven.org/maven2/org/scala-lang/scala-reflect/2.13.3/scala-reflect-2.13.3.jar", |
|||
"/Users/hrbrmstr/Library/Caches/Coursier/v1/https/repo1.maven.org/maven2/org/jline/jline/3.15.0/jline-3.15.0.jar", |
|||
"/Users/hrbrmstr/Library/Caches/Coursier/v1/https/repo1.maven.org/maven2/net/java/dev/jna/jna/5.3.1/jna-5.3.1.jar" |
|||
], |
|||
"analysis": "/Users/hrbrmstr/Development/2020-code-advent/scala/04/04/target/streams/compile/bloopAnalysisOut/_global/streams/inc_compile_2.13.zip", |
|||
"setup": { |
|||
"order": "mixed", |
|||
"addLibraryToBootClasspath": true, |
|||
"addCompilerToClasspath": false, |
|||
"addExtraJarsToClasspath": false, |
|||
"manageBootClasspath": true, |
|||
"filterLibraryFromClasspath": true |
|||
} |
|||
}, |
|||
"java": { |
|||
"options": [ |
|||
|
|||
] |
|||
}, |
|||
"test": { |
|||
"frameworks": [ |
|||
{ |
|||
"names": [ |
|||
"org.scalacheck.ScalaCheckFramework" |
|||
] |
|||
}, |
|||
{ |
|||
"names": [ |
|||
"org.specs2.runner.Specs2Framework", |
|||
"org.specs2.runner.SpecsFramework" |
|||
] |
|||
}, |
|||
{ |
|||
"names": [ |
|||
"org.specs.runner.SpecsFramework" |
|||
] |
|||
}, |
|||
{ |
|||
"names": [ |
|||
"org.scalatest.tools.Framework", |
|||
"org.scalatest.tools.ScalaTestFramework" |
|||
] |
|||
}, |
|||
{ |
|||
"names": [ |
|||
"com.novocode.junit.JUnitFramework" |
|||
] |
|||
} |
|||
], |
|||
"options": { |
|||
"excludes": [ |
|||
|
|||
], |
|||
"arguments": [ |
|||
|
|||
] |
|||
} |
|||
}, |
|||
"platform": { |
|||
"name": "jvm", |
|||
"config": { |
|||
"home": "/Library/Java/JavaVirtualMachines/openjdk-11.0.2.jdk/Contents/Home", |
|||
"options": [ |
|||
"-Duser.dir=/Users/hrbrmstr/Development/2020-code-advent/scala/04/04" |
|||
] |
|||
}, |
|||
"mainClass": [ |
|||
|
|||
] |
|||
}, |
|||
"resolution": { |
|||
"modules": [ |
|||
{ |
|||
"organization": "org.scala-lang", |
|||
"name": "scala-library", |
|||
"version": "2.13.3", |
|||
"configurations": "default", |
|||
"artifacts": [ |
|||
{ |
|||
"name": "scala-library", |
|||
"path": "/Users/hrbrmstr/Library/Caches/Coursier/v1/https/repo1.maven.org/maven2/org/scala-lang/scala-library/2.13.3/scala-library-2.13.3.jar" |
|||
}, |
|||
{ |
|||
"name": "scala-library", |
|||
"classifier": "sources", |
|||
"path": "/Users/hrbrmstr/Library/Caches/Coursier/v1/https/repo1.maven.org/maven2/org/scala-lang/scala-library/2.13.3/scala-library-2.13.3-sources.jar" |
|||
} |
|||
] |
|||
}, |
|||
{ |
|||
"organization": "org.scala-lang.modules", |
|||
"name": "scala-parser-combinators_2.13", |
|||
"version": "1.1.2", |
|||
"configurations": "default", |
|||
"artifacts": [ |
|||
{ |
|||
"name": "scala-parser-combinators_2.13", |
|||
"path": "/Users/hrbrmstr/Library/Caches/Coursier/v1/https/repo1.maven.org/maven2/org/scala-lang/modules/scala-parser-combinators_2.13/1.1.2/scala-parser-combinators_2.13-1.1.2.jar" |
|||
}, |
|||
{ |
|||
"name": "scala-parser-combinators_2.13", |
|||
"classifier": "sources", |
|||
"path": "/Users/hrbrmstr/Library/Caches/Coursier/v1/https/repo1.maven.org/maven2/org/scala-lang/modules/scala-parser-combinators_2.13/1.1.2/scala-parser-combinators_2.13-1.1.2-sources.jar" |
|||
} |
|||
] |
|||
}, |
|||
{ |
|||
"organization": "org.scala-lang", |
|||
"name": "scala-library", |
|||
"version": "2.13.3", |
|||
"configurations": "optional", |
|||
"artifacts": [ |
|||
{ |
|||
"name": "scala-library", |
|||
"path": "/Users/hrbrmstr/Library/Caches/Coursier/v1/https/repo1.maven.org/maven2/org/scala-lang/scala-library/2.13.3/scala-library-2.13.3.jar" |
|||
}, |
|||
{ |
|||
"name": "scala-library", |
|||
"classifier": "sources", |
|||
"path": "/Users/hrbrmstr/Library/Caches/Coursier/v1/https/repo1.maven.org/maven2/org/scala-lang/scala-library/2.13.3/scala-library-2.13.3-sources.jar" |
|||
} |
|||
] |
|||
} |
|||
] |
|||
}, |
|||
"tags": [ |
|||
"library" |
|||
] |
|||
} |
|||
} |
Binary file not shown.
Binary file not shown.
@ -0,0 +1 @@ |
|||
{"name":"sbt","version":"1.4.3","bspVersion":"2.0.0-M5","languages":["scala"],"argv":["/Library/Java/JavaVirtualMachines/zulu-11.jdk/Contents/Home/bin/java","-Xms100m","-Xmx100m","-classpath","/Users/hrbrmstr/.sdkman/candidates/sbt/1.4.4/bin/sbt-launch.jar","xsbt.boot.Boot","-bsp"]} |
Binary file not shown.
@ -0,0 +1,659 @@ |
|||
/* |
|||
* Scala (https://www.scala-lang.org) |
|||
* |
|||
* Copyright EPFL and Lightbend, Inc. |
|||
* |
|||
* Licensed under Apache License 2.0 |
|||
* (http://www.apache.org/licenses/LICENSE-2.0). |
|||
* |
|||
* See the NOTICE file distributed with this work for |
|||
* additional information regarding copyright ownership. |
|||
*/ |
|||
|
|||
package scala |
|||
|
|||
//import scala.collection.generic._ |
|||
import scala.collection.{Factory, immutable, mutable} |
|||
import mutable.ArrayBuilder |
|||
import immutable.ArraySeq |
|||
import scala.language.implicitConversions |
|||
import scala.reflect.ClassTag |
|||
import scala.runtime.BoxedUnit |
|||
import scala.runtime.ScalaRunTime.{array_apply, array_update} |
|||
|
|||
/** Utility methods for operating on arrays. |
|||
* For example: |
|||
* {{{ |
|||
* val a = Array(1, 2) |
|||
* val b = Array.ofDim[Int](2) |
|||
* val c = Array.concat(a, b) |
|||
* }}} |
|||
* where the array objects `a`, `b` and `c` have respectively the values |
|||
* `Array(1, 2)`, `Array(0, 0)` and `Array(1, 2, 0, 0)`. |
|||
*/ |
|||
object Array { |
|||
val emptyBooleanArray = new Array[Boolean](0) |
|||
val emptyByteArray = new Array[Byte](0) |
|||
val emptyCharArray = new Array[Char](0) |
|||
val emptyDoubleArray = new Array[Double](0) |
|||
val emptyFloatArray = new Array[Float](0) |
|||
val emptyIntArray = new Array[Int](0) |
|||
val emptyLongArray = new Array[Long](0) |
|||
val emptyShortArray = new Array[Short](0) |
|||
val emptyObjectArray = new Array[Object](0) |
|||
|
|||
/** Provides an implicit conversion from the Array object to a collection Factory */ |
|||
implicit def toFactory[A : ClassTag](dummy: Array.type): Factory[A, Array[A]] = new ArrayFactory(dummy) |
|||
@SerialVersionUID(3L) |
|||
private class ArrayFactory[A : ClassTag](dummy: Array.type) extends Factory[A, Array[A]] with Serializable { |
|||
def fromSpecific(it: IterableOnce[A]): Array[A] = Array.from[A](it) |
|||
def newBuilder: mutable.Builder[A, Array[A]] = Array.newBuilder[A] |
|||
} |
|||
|
|||
/** |
|||
* Returns a new [[scala.collection.mutable.ArrayBuilder]]. |
|||
*/ |
|||
def newBuilder[T](implicit t: ClassTag[T]): ArrayBuilder[T] = ArrayBuilder.make[T](t) |
|||
|
|||
def from[A : ClassTag](it: IterableOnce[A]): Array[A] = it match { |
|||
case it: Iterable[A] => it.toArray[A] |
|||
case _ => it.iterator.toArray[A] |
|||
} |
|||
|
|||
private def slowcopy(src : AnyRef, |
|||
srcPos : Int, |
|||
dest : AnyRef, |
|||
destPos : Int, |
|||
length : Int): Unit = { |
|||
var i = srcPos |
|||
var j = destPos |
|||
val srcUntil = srcPos + length |
|||
while (i < srcUntil) { |
|||
array_update(dest, j, array_apply(src, i)) |
|||
i += 1 |
|||
j += 1 |
|||
} |
|||
} |
|||
|
|||
/** Copy one array to another. |
|||
* Equivalent to Java's |
|||
* `System.arraycopy(src, srcPos, dest, destPos, length)`, |
|||
* except that this also works for polymorphic and boxed arrays. |
|||
* |
|||
* Note that the passed-in `dest` array will be modified by this call. |
|||
* |
|||
* @param src the source array. |
|||
* @param srcPos starting position in the source array. |
|||
* @param dest destination array. |
|||
* @param destPos starting position in the destination array. |
|||
* @param length the number of array elements to be copied. |
|||
* |
|||
* @see `java.lang.System#arraycopy` |
|||
*/ |
|||
def copy(src: AnyRef, srcPos: Int, dest: AnyRef, destPos: Int, length: Int): Unit = { |
|||
val srcClass = src.getClass |
|||
if (srcClass.isArray && dest.getClass.isAssignableFrom(srcClass)) |
|||
java.lang.System.arraycopy(src, srcPos, dest, destPos, length) |
|||
else |
|||
slowcopy(src, srcPos, dest, destPos, length) |
|||
} |
|||
|
|||
/** Copy one array to another, truncating or padding with default values (if |
|||
* necessary) so the copy has the specified length. |
|||
* |
|||
* Equivalent to Java's |
|||
* `java.util.Arrays.copyOf(original, newLength)`, |
|||
* except that this works for primitive and object arrays in a single method. |
|||
* |
|||
* @see `java.util.Arrays#copyOf` |
|||
*/ |
|||
def copyOf[A](original: Array[A], newLength: Int): Array[A] = (original match { |
|||
case x: Array[BoxedUnit] => newUnitArray(newLength).asInstanceOf[Array[A]] |
|||
case x: Array[AnyRef] => java.util.Arrays.copyOf(x, newLength) |
|||
case x: Array[Int] => java.util.Arrays.copyOf(x, newLength) |
|||
case x: Array[Double] => java.util.Arrays.copyOf(x, newLength) |
|||
case x: Array[Long] => java.util.Arrays.copyOf(x, newLength) |
|||
case x: Array[Float] => java.util.Arrays.copyOf(x, newLength) |
|||
case x: Array[Char] => java.util.Arrays.copyOf(x, newLength) |
|||
case x: Array[Byte] => java.util.Arrays.copyOf(x, newLength) |
|||
case x: Array[Short] => java.util.Arrays.copyOf(x, newLength) |
|||
case x: Array[Boolean] => java.util.Arrays.copyOf(x, newLength) |
|||
}).asInstanceOf[Array[A]] |
|||
|
|||
/** Copy one array to another, truncating or padding with default values (if |
|||
* necessary) so the copy has the specified length. The new array can have |
|||
* a different type than the original one as long as the values are |
|||
* assignment-compatible. When copying between primitive and object arrays, |
|||
* boxing and unboxing are supported. |
|||
* |
|||
* Equivalent to Java's |
|||
* `java.util.Arrays.copyOf(original, newLength, newType)`, |
|||
* except that this works for all combinations of primitive and object arrays |
|||
* in a single method. |
|||
* |
|||
* @see `java.util.Arrays#copyOf` |
|||
*/ |
|||
def copyAs[A](original: Array[_], newLength: Int)(implicit ct: ClassTag[A]): Array[A] = { |
|||
val runtimeClass = ct.runtimeClass |
|||
if (runtimeClass == Void.TYPE) newUnitArray(newLength).asInstanceOf[Array[A]] |
|||
else { |
|||
val destClass = runtimeClass.asInstanceOf[Class[A]] |
|||
if (destClass.isAssignableFrom(original.getClass.getComponentType)) { |
|||
if (destClass.isPrimitive) copyOf[A](original.asInstanceOf[Array[A]], newLength) |
|||
else { |
|||
val destArrayClass = java.lang.reflect.Array.newInstance(destClass, 0).getClass.asInstanceOf[Class[Array[AnyRef]]] |
|||
java.util.Arrays.copyOf(original.asInstanceOf[Array[AnyRef]], newLength, destArrayClass).asInstanceOf[Array[A]] |
|||
} |
|||
} else { |
|||
val dest = new Array[A](newLength) |
|||
Array.copy(original, 0, dest, 0, original.length) |
|||
dest |
|||
} |
|||
} |
|||
} |
|||
|
|||
private def newUnitArray(len: Int): Array[Unit] = { |
|||
val result = new Array[Unit](len) |
|||
java.util.Arrays.fill(result.asInstanceOf[Array[AnyRef]], ()) |
|||
result |
|||
} |
|||
|
|||
/** Returns an array of length 0 */ |
|||
def empty[T: ClassTag]: Array[T] = new Array[T](0) |
|||
|
|||
/** Creates an array with given elements. |
|||
* |
|||
* @param xs the elements to put in the array |
|||
* @return an array containing all elements from xs. |
|||
*/ |
|||
// Subject to a compiler optimization in Cleanup. |
|||
// Array(e0, ..., en) is translated to { val a = new Array(3); a(i) = ei; a } |
|||
def apply[T: ClassTag](xs: T*): Array[T] = { |
|||
val array = new Array[T](xs.length) |
|||
val iterator = xs.iterator |
|||
var i = 0 |
|||
while (iterator.hasNext) { |
|||
array(i) = iterator.next(); i += 1 |
|||
} |
|||
array |
|||
} |
|||
|
|||
/** Creates an array of `Boolean` objects */ |
|||
// Subject to a compiler optimization in Cleanup, see above. |
|||
def apply(x: Boolean, xs: Boolean*): Array[Boolean] = { |
|||
val array = new Array[Boolean](xs.length + 1) |
|||
array(0) = x |
|||
val iterator = xs.iterator |
|||
var i = 1 |
|||
while (iterator.hasNext) { |
|||
array(i) = iterator.next(); i += 1 |
|||
} |
|||
array |
|||
} |
|||
|
|||
/** Creates an array of `Byte` objects */ |
|||
// Subject to a compiler optimization in Cleanup, see above. |
|||
def apply(x: Byte, xs: Byte*): Array[Byte] = { |
|||
val array = new Array[Byte](xs.length + 1) |
|||
array(0) = x |
|||
val iterator = xs.iterator |
|||
var i = 1 |
|||
while (iterator.hasNext) { |
|||
array(i) = iterator.next(); i += 1 |
|||
} |
|||
array |
|||
} |
|||
|
|||
/** Creates an array of `Short` objects */ |
|||
// Subject to a compiler optimization in Cleanup, see above. |
|||
def apply(x: Short, xs: Short*): Array[Short] = { |
|||
val array = new Array[Short](xs.length + 1) |
|||
array(0) = x |
|||
val iterator = xs.iterator |
|||
var i = 1 |
|||
while (iterator.hasNext) { |
|||
array(i) = iterator.next(); i += 1 |
|||
} |
|||
array |
|||
} |
|||
|
|||
/** Creates an array of `Char` objects */ |
|||
// Subject to a compiler optimization in Cleanup, see above. |
|||
def apply(x: Char, xs: Char*): Array[Char] = { |
|||
val array = new Array[Char](xs.length + 1) |
|||
array(0) = x |
|||
val iterator = xs.iterator |
|||
var i = 1 |
|||
while (iterator.hasNext) { |
|||
array(i) = iterator.next(); i += 1 |
|||
} |
|||
array |
|||
} |
|||
|
|||
/** Creates an array of `Int` objects */ |
|||
// Subject to a compiler optimization in Cleanup, see above. |
|||
def apply(x: Int, xs: Int*): Array[Int] = { |
|||
val array = new Array[Int](xs.length + 1) |
|||
array(0) = x |
|||
val iterator = xs.iterator |
|||
var i = 1 |
|||
while (iterator.hasNext) { |
|||
array(i) = iterator.next(); i += 1 |
|||
} |
|||
array |
|||
} |
|||
|
|||
/** Creates an array of `Long` objects */ |
|||
// Subject to a compiler optimization in Cleanup, see above. |
|||
def apply(x: Long, xs: Long*): Array[Long] = { |
|||
val array = new Array[Long](xs.length + 1) |
|||
array(0) = x |
|||
val iterator = xs.iterator |
|||
var i = 1 |
|||
while (iterator.hasNext) { |
|||
array(i) = iterator.next(); i += 1 |
|||
} |
|||
array |
|||
} |
|||
|
|||
/** Creates an array of `Float` objects */ |
|||
// Subject to a compiler optimization in Cleanup, see above. |
|||
def apply(x: Float, xs: Float*): Array[Float] = { |
|||
val array = new Array[Float](xs.length + 1) |
|||
array(0) = x |
|||
val iterator = xs.iterator |
|||
var i = 1 |
|||
while (iterator.hasNext) { |
|||
array(i) = iterator.next(); i += 1 |
|||
} |
|||
array |
|||
} |
|||
|
|||
/** Creates an array of `Double` objects */ |
|||
// Subject to a compiler optimization in Cleanup, see above. |
|||
def apply(x: Double, xs: Double*): Array[Double] = { |
|||
val array = new Array[Double](xs.length + 1) |
|||
array(0) = x |
|||
val iterator = xs.iterator |
|||
var i = 1 |
|||
while (iterator.hasNext) { |
|||
array(i) = iterator.next(); i += 1 |
|||
} |
|||
array |
|||
} |
|||
|
|||
/** Creates an array of `Unit` objects */ |
|||
def apply(x: Unit, xs: Unit*): Array[Unit] = { |
|||
val array = new Array[Unit](xs.length + 1) |
|||
array(0) = x |
|||
val iterator = xs.iterator |
|||
var i = 1 |
|||
while (iterator.hasNext) { |
|||
array(i) = iterator.next(); i += 1 |
|||
} |
|||
array |
|||
} |
|||
|
|||
/** Creates array with given dimensions */ |
|||
def ofDim[T: ClassTag](n1: Int): Array[T] = |
|||
new Array[T](n1) |
|||
/** Creates a 2-dimensional array */ |
|||
def ofDim[T: ClassTag](n1: Int, n2: Int): Array[Array[T]] = { |
|||
val arr: Array[Array[T]] = (new Array[Array[T]](n1): Array[Array[T]]) |
|||
for (i <- 0 until n1) arr(i) = new Array[T](n2) |
|||
arr |
|||
// tabulate(n1)(_ => ofDim[T](n2)) |
|||
} |
|||
/** Creates a 3-dimensional array */ |
|||
def ofDim[T: ClassTag](n1: Int, n2: Int, n3: Int): Array[Array[Array[T]]] = |
|||
tabulate(n1)(_ => ofDim[T](n2, n3)) |
|||
/** Creates a 4-dimensional array */ |
|||
def ofDim[T: ClassTag](n1: Int, n2: Int, n3: Int, n4: Int): Array[Array[Array[Array[T]]]] = |
|||
tabulate(n1)(_ => ofDim[T](n2, n3, n4)) |
|||
/** Creates a 5-dimensional array */ |
|||
def ofDim[T: ClassTag](n1: Int, n2: Int, n3: Int, n4: Int, n5: Int): Array[Array[Array[Array[Array[T]]]]] = |
|||
tabulate(n1)(_ => ofDim[T](n2, n3, n4, n5)) |
|||
|
|||
/** Concatenates all arrays into a single array. |
|||
* |
|||
* @param xss the given arrays |
|||
* @return the array created from concatenating `xss` |
|||
*/ |
|||
def concat[T: ClassTag](xss: Array[T]*): Array[T] = { |
|||
val b = newBuilder[T] |
|||
b.sizeHint(xss.map(_.length).sum) |
|||
for (xs <- xss) b ++= xs |
|||
b.result() |
|||
} |
|||
|
|||
/** Returns an array that contains the results of some element computation a number |
|||
* of times. |
|||
* |
|||
* Note that this means that `elem` is computed a total of n times: |
|||
* {{{ |
|||
* scala> Array.fill(3){ math.random } |
|||
* res3: Array[Double] = Array(0.365461167592537, 1.550395944913685E-4, 0.7907242137333306) |
|||
* }}} |
|||
* |
|||
* @param n the number of elements desired |
|||
* @param elem the element computation |
|||
* @return an Array of size n, where each element contains the result of computing |
|||
* `elem`. |
|||
*/ |
|||
def fill[T: ClassTag](n: Int)(elem: => T): Array[T] = { |
|||
if (n <= 0) { |
|||
empty[T] |
|||
} else { |
|||
val array = new Array[T](n) |
|||
var i = 0 |
|||
while (i < n) { |
|||
array(i) = elem |
|||
i += 1 |
|||
} |
|||
array |
|||
} |
|||
} |
|||
|
|||
/** Returns a two-dimensional array that contains the results of some element |
|||
* computation a number of times. |
|||
* |
|||
* @param n1 the number of elements in the 1st dimension |
|||
* @param n2 the number of elements in the 2nd dimension |
|||
* @param elem the element computation |
|||
*/ |
|||
def fill[T: ClassTag](n1: Int, n2: Int)(elem: => T): Array[Array[T]] = |
|||
tabulate(n1)(_ => fill(n2)(elem)) |
|||
|
|||
/** Returns a three-dimensional array that contains the results of some element |
|||
* computation a number of times. |
|||
* |
|||
* @param n1 the number of elements in the 1st dimension |
|||
* @param n2 the number of elements in the 2nd dimension |
|||
* @param n3 the number of elements in the 3rd dimension |
|||
* @param elem the element computation |
|||
*/ |
|||
def fill[T: ClassTag](n1: Int, n2: Int, n3: Int)(elem: => T): Array[Array[Array[T]]] = |
|||
tabulate(n1)(_ => fill(n2, n3)(elem)) |
|||
|
|||
/** Returns a four-dimensional array that contains the results of some element |
|||
* computation a number of times. |
|||
* |
|||
* @param n1 the number of elements in the 1st dimension |
|||
* @param n2 the number of elements in the 2nd dimension |
|||
* @param n3 the number of elements in the 3rd dimension |
|||
* @param n4 the number of elements in the 4th dimension |
|||
* @param elem the element computation |
|||
*/ |
|||
def fill[T: ClassTag](n1: Int, n2: Int, n3: Int, n4: Int)(elem: => T): Array[Array[Array[Array[T]]]] = |
|||
tabulate(n1)(_ => fill(n2, n3, n4)(elem)) |
|||
|
|||
/** Returns a five-dimensional array that contains the results of some element |
|||
* computation a number of times. |
|||
* |
|||
* @param n1 the number of elements in the 1st dimension |
|||
* @param n2 the number of elements in the 2nd dimension |
|||
* @param n3 the number of elements in the 3rd dimension |
|||
* @param n4 the number of elements in the 4th dimension |
|||
* @param n5 the number of elements in the 5th dimension |
|||
* @param elem the element computation |
|||
*/ |
|||
def fill[T: ClassTag](n1: Int, n2: Int, n3: Int, n4: Int, n5: Int)(elem: => T): Array[Array[Array[Array[Array[T]]]]] = |
|||
tabulate(n1)(_ => fill(n2, n3, n4, n5)(elem)) |
|||
|
|||
/** Returns an array containing values of a given function over a range of integer |
|||
* values starting from 0. |
|||
* |
|||
* @param n The number of elements in the array |
|||
* @param f The function computing element values |
|||
* @return A traversable consisting of elements `f(0),f(1), ..., f(n - 1)` |
|||
*/ |
|||
def tabulate[T: ClassTag](n: Int)(f: Int => T): Array[T] = { |
|||
if (n <= 0) { |
|||
empty[T] |
|||
} else { |
|||
val array = new Array[T](n) |
|||
var i = 0 |
|||
while (i < n) { |
|||
array(i) = f(i) |
|||
i += 1 |
|||
} |
|||
array |
|||
} |
|||
} |
|||
|
|||
/** Returns a two-dimensional array containing values of a given function |
|||
* over ranges of integer values starting from `0`. |
|||
* |
|||
* @param n1 the number of elements in the 1st dimension |
|||
* @param n2 the number of elements in the 2nd dimension |
|||
* @param f The function computing element values |
|||
*/ |
|||
def tabulate[T: ClassTag](n1: Int, n2: Int)(f: (Int, Int) => T): Array[Array[T]] = |
|||
tabulate(n1)(i1 => tabulate(n2)(f(i1, _))) |
|||
|
|||
/** Returns a three-dimensional array containing values of a given function |
|||
* over ranges of integer values starting from `0`. |
|||
* |
|||
* @param n1 the number of elements in the 1st dimension |
|||
* @param n2 the number of elements in the 2nd dimension |
|||
* @param n3 the number of elements in the 3rd dimension |
|||
* @param f The function computing element values |
|||
*/ |
|||
def tabulate[T: ClassTag](n1: Int, n2: Int, n3: Int)(f: (Int, Int, Int) => T): Array[Array[Array[T]]] = |
|||
tabulate(n1)(i1 => tabulate(n2, n3)(f(i1, _, _))) |
|||
|
|||
/** Returns a four-dimensional array containing values of a given function |
|||
* over ranges of integer values starting from `0`. |
|||
* |
|||
* @param n1 the number of elements in the 1st dimension |
|||
* @param n2 the number of elements in the 2nd dimension |
|||
* @param n3 the number of elements in the 3rd dimension |
|||
* @param n4 the number of elements in the 4th dimension |
|||
* @param f The function computing element values |
|||
*/ |
|||
def tabulate[T: ClassTag](n1: Int, n2: Int, n3: Int, n4: Int)(f: (Int, Int, Int, Int) => T): Array[Array[Array[Array[T]]]] = |
|||
tabulate(n1)(i1 => tabulate(n2, n3, n4)(f(i1, _, _, _))) |
|||
|
|||
/** Returns a five-dimensional array containing values of a given function |
|||
* over ranges of integer values starting from `0`. |
|||
* |
|||
* @param n1 the number of elements in the 1st dimension |
|||
* @param n2 the number of elements in the 2nd dimension |
|||
* @param n3 the number of elements in the 3rd dimension |
|||
* @param n4 the number of elements in the 4th dimension |
|||
* @param n5 the number of elements in the 5th dimension |
|||
* @param f The function computing element values |
|||
*/ |
|||
def tabulate[T: ClassTag](n1: Int, n2: Int, n3: Int, n4: Int, n5: Int)(f: (Int, Int, Int, Int, Int) => T): Array[Array[Array[Array[Array[T]]]]] = |
|||
tabulate(n1)(i1 => tabulate(n2, n3, n4, n5)(f(i1, _, _, _, _))) |
|||
|
|||
/** Returns an array containing a sequence of increasing integers in a range. |
|||
* |
|||
* @param start the start value of the array |
|||
* @param end the end value of the array, exclusive (in other words, this is the first value '''not''' returned) |
|||
* @return the array with values in range `start, start + 1, ..., end - 1` |
|||
* up to, but excluding, `end`. |
|||
*/ |
|||
def range(start: Int, end: Int): Array[Int] = range(start, end, 1) |
|||
|
|||
/** Returns an array containing equally spaced values in some integer interval. |
|||
* |
|||
* @param start the start value of the array |
|||
* @param end the end value of the array, exclusive (in other words, this is the first value '''not''' returned) |
|||
* @param step the increment value of the array (may not be zero) |
|||
* @return the array with values in `start, start + step, ...` up to, but excluding `end` |
|||
*/ |
|||
def range(start: Int, end: Int, step: Int): Array[Int] = { |
|||
if (step == 0) throw new IllegalArgumentException("zero step") |
|||
val array = new Array[Int](immutable.Range.count(start, end, step, isInclusive = false)) |
|||
|
|||
var n = 0 |
|||
var i = start |
|||
while (if (step < 0) end < i else i < end) { |
|||
array(n) = i |
|||
i += step |
|||
n += 1 |
|||
} |
|||
array |
|||
} |
|||
|
|||
/** Returns an array containing repeated applications of a function to a start value. |
|||
* |
|||
* @param start the start value of the array |
|||
* @param len the number of elements returned by the array |
|||
* @param f the function that is repeatedly applied |
|||
* @return the array returning `len` values in the sequence `start, f(start), f(f(start)), ...` |
|||
*/ |
|||
def iterate[T: ClassTag](start: T, len: Int)(f: T => T): Array[T] = { |
|||
if (len > 0) { |
|||
val array = new Array[T](len) |
|||
var acc = start |
|||
var i = 1 |
|||
array(0) = acc |
|||
|
|||
while (i < len) { |
|||
acc = f(acc) |
|||
array(i) = acc |
|||
i += 1 |
|||
} |
|||
array |
|||
} else { |
|||
empty[T] |
|||
} |
|||
} |
|||
|
|||
def equals(xs: Array[AnyRef], ys: Array[AnyRef]): Boolean = { |
|||
if (xs eq ys) |
|||
return true |
|||
if (xs.length != ys.length) |
|||
return false |
|||
|
|||
val len = xs.length |
|||
var i = 0 |
|||
while (i < len) { |
|||
if (xs(i) != ys(i)) |
|||
return false |
|||
i += 1 |
|||
} |
|||
true |
|||
} |
|||
|
|||
/** Called in a pattern match like `{ case Array(x,y,z) => println('3 elements')}`. |
|||
* |
|||
* @param x the selector value |
|||
* @return sequence wrapped in a [[scala.Some]], if `x` is an Array, otherwise `None` |
|||
*/ |
|||
def unapplySeq[T](x: Array[T]): UnapplySeqWrapper[T] = new UnapplySeqWrapper(x) |
|||
|
|||
final class UnapplySeqWrapper[T](private val a: Array[T]) extends AnyVal { |
|||
def isEmpty: Boolean = false |
|||
def get: UnapplySeqWrapper[T] = this |
|||
def lengthCompare(len: Int): Int = a.lengthCompare(len) |
|||
def apply(i: Int): T = a(i) |
|||
def drop(n: Int): scala.Seq[T] = ArraySeq.unsafeWrapArray(a.drop(n)) // clones the array, also if n == 0 |
|||
def toSeq: scala.Seq[T] = a.toSeq // clones the array |
|||
} |
|||
} |
|||
|
|||
/** Arrays are mutable, indexed collections of values. `Array[T]` is Scala's representation |
|||
* for Java's `T[]`. |
|||
* |
|||
* {{{ |
|||
* val numbers = Array(1, 2, 3, 4) |
|||
* val first = numbers(0) // read the first element |
|||
* numbers(3) = 100 // replace the 4th array element with 100 |
|||
* val biggerNumbers = numbers.map(_ * 2) // multiply all numbers by two |
|||
* }}} |
|||
* |
|||
* Arrays make use of two common pieces of Scala syntactic sugar, shown on lines 2 and 3 of the above |
|||
* example code. |
|||
* Line 2 is translated into a call to `apply(Int)`, while line 3 is translated into a call to |
|||
* `update(Int, T)`. |
|||
* |
|||
* Two implicit conversions exist in [[scala.Predef]] that are frequently applied to arrays: a conversion |
|||
* to [[scala.collection.ArrayOps]] (shown on line 4 of the example above) and a conversion |
|||
* to [[scala.collection.mutable.ArraySeq]] (a subtype of [[scala.collection.Seq]]). |
|||
* Both types make available many of the standard operations found in the Scala collections API. |
|||
* The conversion to `ArrayOps` is temporary, as all operations defined on `ArrayOps` return an `Array`, |
|||
* while the conversion to `ArraySeq` is permanent as all operations return a `ArraySeq`. |
|||
* |
|||
* The conversion to `ArrayOps` takes priority over the conversion to `ArraySeq`. For instance, |
|||
* consider the following code: |
|||
* |
|||
* {{{ |
|||
* val arr = Array(1, 2, 3) |
|||
* val arrReversed = arr.reverse |
|||
* val seqReversed : collection.Seq[Int] = arr.reverse |
|||
* }}} |
|||
* |
|||
* Value `arrReversed` will be of type `Array[Int]`, with an implicit conversion to `ArrayOps` occurring |
|||
* to perform the `reverse` operation. The value of `seqReversed`, on the other hand, will be computed |
|||
* by converting to `ArraySeq` first and invoking the variant of `reverse` that returns another |
|||
* `ArraySeq`. |
|||
* |
|||
* @see [[http://www.scala-lang.org/files/archive/spec/2.13/ Scala Language Specification]], for in-depth information on the transformations the Scala compiler makes on Arrays (Sections 6.6 and 6.15 respectively.) |
|||
* @see [[http://docs.scala-lang.org/sips/completed/scala-2-8-arrays.html "Scala 2.8 Arrays"]] the Scala Improvement Document detailing arrays since Scala 2.8. |
|||
* @see [[http://docs.scala-lang.org/overviews/collections/arrays.html "The Scala 2.8 Collections' API"]] section on `Array` by Martin Odersky for more information. |
|||
* @hideImplicitConversion scala.Predef.booleanArrayOps |
|||
* @hideImplicitConversion scala.Predef.byteArrayOps |
|||
* @hideImplicitConversion scala.Predef.charArrayOps |
|||
* @hideImplicitConversion scala.Predef.doubleArrayOps |
|||
* @hideImplicitConversion scala.Predef.floatArrayOps |
|||
* @hideImplicitConversion scala.Predef.intArrayOps |
|||
* @hideImplicitConversion scala.Predef.longArrayOps |
|||
* @hideImplicitConversion scala.Predef.refArrayOps |
|||
* @hideImplicitConversion scala.Predef.shortArrayOps |
|||
* @hideImplicitConversion scala.Predef.unitArrayOps |
|||
* @hideImplicitConversion scala.LowPriorityImplicits.wrapRefArray |
|||
* @hideImplicitConversion scala.LowPriorityImplicits.wrapIntArray |
|||
* @hideImplicitConversion scala.LowPriorityImplicits.wrapDoubleArray |
|||
* @hideImplicitConversion scala.LowPriorityImplicits.wrapLongArray |
|||
* @hideImplicitConversion scala.LowPriorityImplicits.wrapFloatArray |
|||
* @hideImplicitConversion scala.LowPriorityImplicits.wrapCharArray |
|||
* @hideImplicitConversion scala.LowPriorityImplicits.wrapByteArray |
|||
* @hideImplicitConversion scala.LowPriorityImplicits.wrapShortArray |
|||
* @hideImplicitConversion scala.LowPriorityImplicits.wrapBooleanArray |
|||
* @hideImplicitConversion scala.LowPriorityImplicits.wrapUnitArray |
|||
* @hideImplicitConversion scala.LowPriorityImplicits.genericWrapArray |
|||
* @define coll array |
|||
* @define Coll `Array` |
|||
* @define orderDependent |
|||
* @define orderDependentFold |
|||
* @define mayNotTerminateInf |
|||
* @define willNotTerminateInf |
|||
* @define collectExample |
|||
* @define undefinedorder |
|||
*/ |
|||
final class Array[T](_length: Int) extends java.io.Serializable with java.lang.Cloneable { |
|||
|
|||
/** The length of the array */ |
|||
def length: Int = throw new Error() |
|||
|
|||
/** The element at given index. |
|||
* |
|||
* Indices start at `0`; `xs.apply(0)` is the first element of array `xs`. |
|||
* Note the indexing syntax `xs(i)` is a shorthand for `xs.apply(i)`. |
|||
* |
|||
* @param i the index |
|||
* @return the element at the given index |
|||
* @throws ArrayIndexOutOfBoundsException if `i < 0` or `length <= i` |
|||
*/ |
|||
def apply(i: Int): T = throw new Error() |
|||
|
|||
/** Update the element at given index. |
|||
* |
|||
* Indices start at `0`; `xs.update(i, x)` replaces the i^th^ element in the array. |
|||
* Note the syntax `xs(i) = x` is a shorthand for `xs.update(i, x)`. |
|||
* |
|||
* @param i the index |
|||
* @param x the value to be written at index `i` |
|||
* @throws ArrayIndexOutOfBoundsException if `i < 0` or `length <= i` |
|||
*/ |
|||
def update(i: Int, x: T): Unit = { throw new Error() } |
|||
|
|||
/** Clone the Array. |
|||
* |
|||
* @return A clone of the Array. |
|||
*/ |
|||
override def clone(): Array[T] = throw new Error() |
|||
} |
@ -0,0 +1,140 @@ |
|||
/* |
|||
* Scala (https://www.scala-lang.org) |
|||
* |
|||
* Copyright EPFL and Lightbend, Inc. |
|||
* |
|||
* Licensed under Apache License 2.0 |
|||
* (http://www.apache.org/licenses/LICENSE-2.0). |
|||
* |
|||
* See the NOTICE file distributed with this work for |
|||
* additional information regarding copyright ownership. |
|||
*/ |
|||
|
|||
// DO NOT EDIT, CHANGES WILL BE LOST |
|||
// This auto-generated code can be modified in "project/GenerateAnyVals.scala". |
|||
// Afterwards, running "sbt generateSources" regenerates this source file. |
|||
|
|||
package scala |
|||
|
|||
/** `Boolean` (equivalent to Java's `boolean` primitive type) is a |
|||
* subtype of [[scala.AnyVal]]. Instances of `Boolean` are not |
|||
* represented by an object in the underlying runtime system. |
|||
* |
|||
* There is an implicit conversion from [[scala.Boolean]] => [[scala.runtime.RichBoolean]] |
|||
* which provides useful non-primitive operations. |
|||
*/ |
|||
final abstract class Boolean private extends AnyVal { |
|||
/** Negates a Boolean expression. |
|||
* |
|||
* - `!a` results in `false` if and only if `a` evaluates to `true` and |
|||
* - `!a` results in `true` if and only if `a` evaluates to `false`. |
|||
* |
|||
* @return the negated expression |
|||
*/ |
|||
def unary_! : Boolean |
|||
|
|||
/** Compares two Boolean expressions and returns `true` if they evaluate to the same value. |
|||
* |
|||
* `a == b` returns `true` if and only if |
|||
* - `a` and `b` are `true` or |
|||
* - `a` and `b` are `false`. |
|||
*/ |
|||
def ==(x: Boolean): Boolean |
|||
|
|||
/** |
|||
* Compares two Boolean expressions and returns `true` if they evaluate to a different value. |
|||
* |
|||
* `a != b` returns `true` if and only if |
|||
* - `a` is `true` and `b` is `false` or |
|||
* - `a` is `false` and `b` is `true`. |
|||
*/ |
|||
def !=(x: Boolean): Boolean |
|||
|
|||
/** Compares two Boolean expressions and returns `true` if one or both of them evaluate to true. |
|||
* |
|||
* `a || b` returns `true` if and only if |
|||
* - `a` is `true` or |
|||
* - `b` is `true` or |
|||
* - `a` and `b` are `true`. |
|||
* |
|||
* @note This method uses 'short-circuit' evaluation and |
|||
* behaves as if it was declared as `def ||(x: => Boolean): Boolean`. |
|||
* If `a` evaluates to `true`, `true` is returned without evaluating `b`. |
|||
*/ |
|||
def ||(x: Boolean): Boolean |
|||
|
|||
/** Compares two Boolean expressions and returns `true` if both of them evaluate to true. |
|||
* |
|||
* `a && b` returns `true` if and only if |
|||
* - `a` and `b` are `true`. |
|||
* |
|||
* @note This method uses 'short-circuit' evaluation and |
|||
* behaves as if it was declared as `def &&(x: => Boolean): Boolean`. |
|||
* If `a` evaluates to `false`, `false` is returned without evaluating `b`. |
|||
*/ |
|||
def &&(x: Boolean): Boolean |
|||
|
|||
// Compiler won't build with these seemingly more accurate signatures |
|||
// def ||(x: => Boolean): Boolean |
|||
// def &&(x: => Boolean): Boolean |
|||
|
|||
/** Compares two Boolean expressions and returns `true` if one or both of them evaluate to true. |
|||
* |
|||
* `a | b` returns `true` if and only if |
|||
* - `a` is `true` or |
|||
* - `b` is `true` or |
|||
* - `a` and `b` are `true`. |
|||
* |
|||
* @note This method evaluates both `a` and `b`, even if the result is already determined after evaluating `a`. |
|||
*/ |
|||
def |(x: Boolean): Boolean |
|||
|
|||
/** Compares two Boolean expressions and returns `true` if both of them evaluate to true. |
|||
* |
|||
* `a & b` returns `true` if and only if |
|||
* - `a` and `b` are `true`. |
|||
* |
|||
* @note This method evaluates both `a` and `b`, even if the result is already determined after evaluating `a`. |
|||
*/ |
|||
def &(x: Boolean): Boolean |
|||
|
|||
/** Compares two Boolean expressions and returns `true` if they evaluate to a different value. |
|||
* |
|||
* `a ^ b` returns `true` if and only if |
|||
* - `a` is `true` and `b` is `false` or |
|||
* - `a` is `false` and `b` is `true`. |
|||
*/ |
|||
def ^(x: Boolean): Boolean |
|||
|
|||
// Provide a more specific return type for Scaladoc |
|||
override def getClass(): Class[Boolean] = ??? |
|||
} |
|||
|
|||
object Boolean extends AnyValCompanion { |
|||
|
|||
/** Transform a value type into a boxed reference type. |
|||
* |
|||
* Runtime implementation determined by `scala.runtime.BoxesRunTime.boxToBoolean`. See [[https://github.com/scala/scala src/library/scala/runtime/BoxesRunTime.java]]. |
|||
* |
|||
* @param x the Boolean to be boxed |
|||
* @return a java.lang.Boolean offering `x` as its underlying value. |
|||
*/ |
|||
def box(x: Boolean): java.lang.Boolean = ??? |
|||
|
|||
/** Transform a boxed type into a value type. Note that this |
|||
* method is not typesafe: it accepts any Object, but will throw |
|||
* an exception if the argument is not a java.lang.Boolean. |
|||
* |
|||
* Runtime implementation determined by `scala.runtime.BoxesRunTime.unboxToBoolean`. See [[https://github.com/scala/scala src/library/scala/runtime/BoxesRunTime.java]]. |
|||
* |
|||
* @param x the java.lang.Boolean to be unboxed. |
|||
* @throws ClassCastException if the argument is not a java.lang.Boolean |
|||
* @return the Boolean resulting from calling booleanValue() on `x` |
|||
*/ |
|||
def unbox(x: java.lang.Object): Boolean = ??? |
|||
|
|||
/** The String representation of the scala.Boolean companion object. */ |
|||
override def toString = "object scala.Boolean" |
|||
|
|||
} |
|||
|
@ -0,0 +1,581 @@ |
|||
/* |
|||
* Scala (https://www.scala-lang.org) |
|||
* |
|||
* Copyright EPFL and Lightbend, Inc. |
|||
* |
|||
* Licensed under Apache License 2.0 |
|||
* (http://www.apache.org/licenses/LICENSE-2.0). |
|||
* |
|||
* See the NOTICE file distributed with this work for |
|||
* additional information regarding copyright ownership. |
|||
*/ |
|||
|
|||
package scala |
|||
|
|||
import scala.language.implicitConversions |
|||
|
|||
import scala.collection.{mutable, immutable, ArrayOps, StringOps}, immutable.WrappedString |
|||
import scala.annotation.{elidable, implicitNotFound}, elidable.ASSERTION |
|||
import scala.annotation.meta.{ companionClass, companionMethod } |
|||
|
|||
/** The `Predef` object provides definitions that are accessible in all Scala |
|||
* compilation units without explicit qualification. |
|||
* |
|||
* === Commonly Used Types === |
|||
* Predef provides type aliases for types which are commonly used, such as |
|||
* the immutable collection types [[scala.collection.immutable.Map]], |
|||
* [[scala.collection.immutable.Set]], and the [[scala.collection.immutable.List]] |
|||
* constructors ([[scala.collection.immutable.::]] and |
|||
* [[scala.collection.immutable.Nil]]). |
|||
* |
|||
* === Console Output === |
|||
* For basic console output, `Predef` provides convenience methods [[print(x:Any* print]] and [[println(x:Any* println]], |
|||
* which are aliases of the methods in the object [[scala.Console]]. |
|||
* |
|||
* === Assertions === |
|||
* A set of `assert` functions are provided for use as a way to document |
|||
* and dynamically check invariants in code. Invocations of `assert` can be elided |
|||
* at compile time by providing the command line option `-Xdisable-assertions`, |
|||
* which raises `-Xelide-below` above `elidable.ASSERTION`, to the `scalac` command. |
|||
* |
|||
* Variants of `assert` intended for use with static analysis tools are also |
|||
* provided: `assume`, `require` and `ensuring`. `require` and `ensuring` are |
|||
* intended for use as a means of design-by-contract style specification |
|||
* of pre- and post-conditions on functions, with the intention that these |
|||
* specifications could be consumed by a static analysis tool. For instance, |
|||
* |
|||
* {{{ |
|||
* def addNaturals(nats: List[Int]): Int = { |
|||
* require(nats forall (_ >= 0), "List contains negative numbers") |
|||
* nats.foldLeft(0)(_ + _) |
|||
* } ensuring(_ >= 0) |
|||
* }}} |
|||
* |
|||
* The declaration of `addNaturals` states that the list of integers passed should |
|||
* only contain natural numbers (i.e. non-negative), and that the result returned |
|||
* will also be natural. `require` is distinct from `assert` in that if the |
|||
* condition fails, then the caller of the function is to blame rather than a |
|||
* logical error having been made within `addNaturals` itself. `ensuring` is a |
|||
* form of `assert` that declares the guarantee the function is providing with |
|||
* regards to its return value. |
|||
* |
|||
* === Implicit Conversions === |
|||
* A number of commonly applied implicit conversions are also defined here, and |
|||
* in the parent type [[scala.LowPriorityImplicits]]. Implicit conversions |
|||
* are provided for the "widening" of numeric values, for instance, converting a |
|||
* Short value to a Long value as required, and to add additional higher-order |
|||
* functions to Array values. These are described in more detail in the documentation of [[scala.Array]]. |
|||
* |
|||
* @groupname utilities Utility Methods |
|||
* @groupprio utilities 10 |
|||
* |
|||
* @groupname assertions Assertions |
|||
* @groupprio assertions 20 |
|||
* @groupdesc assertions These methods support program verification and runtime correctness. |
|||
* |
|||
* @groupname console-output Console Output |
|||
* @groupprio console-output 30 |
|||
* @groupdesc console-output These methods provide output via the console. |
|||
* |
|||
* @groupname aliases Aliases |
|||
* @groupprio aliases 50 |
|||
* @groupdesc aliases These aliases bring selected immutable types into scope without any imports. |
|||
* |
|||
* @groupname conversions-string String Conversions |
|||
* @groupprio conversions-string 60 |
|||
* @groupdesc conversions-string Conversions from String to StringOps or WrappedString. |
|||
* |
|||
* @groupname implicit-classes-any Implicit Classes |
|||
* @groupprio implicit-classes-any 70 |
|||
* @groupdesc implicit-classes-any These implicit classes add useful extension methods to every type. |
|||
* |
|||
* @groupname implicit-classes-char CharSequence Conversions |
|||
* @groupprio implicit-classes-char 80 |
|||
* @groupdesc implicit-classes-char These implicit classes add CharSequence methods to Array[Char] and IndexedSeq[Char] instances. |
|||
* |
|||
* @groupname conversions-java-to-anyval Java to Scala |
|||
* @groupprio conversions-java-to-anyval 90 |
|||
* @groupdesc conversions-java-to-anyval Implicit conversion from Java primitive wrapper types to Scala equivalents. |
|||
* |
|||
* @groupname conversions-anyval-to-java Scala to Java |
|||
* @groupprio conversions-anyval-to-java 100 |
|||
* @groupdesc conversions-anyval-to-java Implicit conversion from Scala AnyVals to Java primitive wrapper types equivalents. |
|||
* |
|||
* @groupname conversions-array-to-wrapped-array Array to ArraySeq |
|||
* @groupprio conversions-array-to-wrapped-array 110 |
|||
* @groupdesc conversions-array-to-wrapped-array Conversions from Arrays to ArraySeqs. |
|||
*/ |
|||
object Predef extends LowPriorityImplicits { |
|||
/** |
|||
* Retrieve the runtime representation of a class type. `classOf[T]` is equivalent to |
|||
* the class literal `T.class` in Java. |
|||
* |
|||
* @example {{{ |
|||
* val listClass = classOf[List[_]] |
|||
* // listClass is java.lang.Class[List[_]] = class scala.collection.immutable.List |
|||
* |
|||
* val mapIntString = classOf[Map[Int,String]] |
|||
* // mapIntString is java.lang.Class[Map[Int,String]] = interface scala.collection.immutable.Map |
|||
* }}} |
|||
* |
|||
* @return The runtime [[Class]] representation of type `T`. |
|||
* @group utilities |
|||
*/ |
|||
def classOf[T]: Class[T] = null // This is a stub method. The actual implementation is filled in by the compiler. |
|||
|
|||
/** |
|||
* Retrieve the single value of a type with a unique inhabitant. |
|||
* |
|||
* @example {{{ |
|||
* object Foo |
|||
* val foo = valueOf[Foo.type] |
|||
* // foo is Foo.type = Foo |
|||
* |
|||
* val bar = valueOf[23] |
|||
* // bar is 23.type = 23 |
|||
* }}} |
|||
* @group utilities |
|||
*/ |
|||
@inline def valueOf[T](implicit vt: ValueOf[T]): T = vt.value |
|||
|
|||
/** The `String` type in Scala has all the methods of the underlying |
|||
* `java.lang.String`, of which it is just an alias. |
|||
* (See the documentation corresponding to your Java version, |
|||
* for example [[http://docs.oracle.com/javase/8/docs/api/java/lang/String.html]].) |
|||
* In addition, extension methods in [[scala.collection.StringOps]] |
|||
* are added implicitly through the conversion [[augmentString]]. |
|||
* @group aliases |
|||
*/ |
|||
type String = java.lang.String |
|||
/** @group aliases */ |
|||
type Class[T] = java.lang.Class[T] |
|||
|
|||
// miscellaneous ----------------------------------------------------- |
|||
scala.`package` // to force scala package object to be seen. |
|||
scala.collection.immutable.List // to force Nil, :: to be seen. |
|||
|
|||
/** @group aliases */ |
|||
type Function[-A, +B] = Function1[A, B] |
|||
|
|||
/** @group aliases */ |
|||
type Map[K, +V] = immutable.Map[K, V] |
|||
/** @group aliases */ |
|||
type Set[A] = immutable.Set[A] |
|||
/** @group aliases */ |
|||
val Map = immutable.Map |
|||
/** @group aliases */ |
|||
val Set = immutable.Set |
|||
|
|||
/** |
|||
* Allows destructuring tuples with the same syntax as constructing them. |
|||
* |
|||
* @example {{{ |
|||
* val tup = "foobar" -> 3 |
|||
* |
|||
* val c = tup match { |
|||
* case str -> i => str.charAt(i) |
|||
* } |
|||
* }}} |
|||
* @group aliases |
|||
*/ |
|||
val -> = Tuple2 |
|||
|
|||
// Manifest types, companions, and incantations for summoning |
|||
// TODO undeprecated until Scala reflection becomes non-experimental |
|||
// @deprecated("this notion doesn't have a corresponding concept in 2.10, because scala.reflect.runtime.universe.TypeTag can capture arbitrary types. Use type tags instead of manifests, and there will be no need in opt manifests.", "2.10.0") |
|||
type OptManifest[T] = scala.reflect.OptManifest[T] |
|||
@implicitNotFound(msg = "No Manifest available for ${T}.") |
|||
// TODO undeprecated until Scala reflection becomes non-experimental |
|||
// @deprecated("use `scala.reflect.ClassTag` (to capture erasures) or scala.reflect.runtime.universe.TypeTag (to capture types) or both instead", "2.10.0") |
|||
type Manifest[T] = scala.reflect.Manifest[T] |
|||
// TODO undeprecated until Scala reflection becomes non-experimental |
|||
// @deprecated("use `scala.reflect.ClassTag` (to capture erasures) or scala.reflect.runtime.universe.TypeTag (to capture types) or both instead", "2.10.0") |
|||
val Manifest = scala.reflect.Manifest |
|||
// TODO undeprecated until Scala reflection becomes non-experimental |
|||
// @deprecated("this notion doesn't have a corresponding concept in 2.10, because scala.reflect.runtime.universe.TypeTag can capture arbitrary types. Use type tags instead of manifests, and there will be no need in opt manifests.", "2.10.0") |
|||
val NoManifest = scala.reflect.NoManifest |
|||
|
|||
// TODO undeprecated until Scala reflection becomes non-experimental |
|||
// @deprecated("use scala.reflect.classTag[T] and scala.reflect.runtime.universe.typeTag[T] instead", "2.10.0") |
|||
def manifest[T](implicit m: Manifest[T]): Manifest[T] = m |
|||
// TODO undeprecated until Scala reflection becomes non-experimental |
|||
// @deprecated("this notion doesn't have a corresponding concept in 2.10, because scala.reflect.runtime.universe.TypeTag can capture arbitrary types. Use type tags instead of manifests, and there will be no need in opt manifests.", "2.10.0") |
|||
def optManifest[T](implicit m: OptManifest[T]): OptManifest[T] = m |
|||
|
|||
// Minor variations on identity functions |
|||
|
|||
/** |
|||
* A method that returns its input value. |
|||
* @tparam A type of the input value x. |
|||
* @param x the value of type `A` to be returned. |
|||
* @return the value `x`. |
|||
* @group utilities */ |
|||
@inline def identity[A](x: A): A = x // see `$conforms` for the implicit version |
|||
|
|||
/** Summon an implicit value of type `T`. Usually, the argument is not passed explicitly. |
|||
* |
|||
* @tparam T the type of the value to be summoned |
|||
* @return the implicit value of type `T` |
|||
* @group utilities |
|||
*/ |
|||
@inline def implicitly[T](implicit e: T): T = e // TODO: when dependent method types are on by default, give this result type `e.type`, so that inliner has better chance of knowing which method to inline in calls like `implicitly[MatchingStrategy[Option]].zero` |
|||
|
|||
/** Used to mark code blocks as being expressions, instead of being taken as part of anonymous classes and the like. |
|||
* This is just a different name for [[identity]]. |
|||
* |
|||
* @example Separating code blocks from `new`: |
|||
* {{{ |
|||
* val x = new AnyRef |
|||
* { |
|||
* val y = ... |
|||
* println(y) |
|||
* } |
|||
* // the { ... } block is seen as the body of an anonymous class |
|||
* |
|||
* val x = new AnyRef |
|||
* |
|||
* { |
|||
* val y = ... |
|||
* println(y) |
|||
* } |
|||
* // an empty line is a brittle "fix" |
|||
* |
|||
* val x = new AnyRef |
|||
* locally { |
|||
* val y = ... |
|||
* println(y) |
|||
* } |
|||
* // locally guards the block and helps communicate intent |
|||
* }}} |
|||
* @group utilities |
|||
*/ |
|||
@inline def locally[T](@deprecatedName("x") x: T): T = x |
|||
|
|||
// assertions --------------------------------------------------------- |
|||
|
|||
/** Tests an expression, throwing an `AssertionError` if false. |
|||
* Calls to this method will not be generated if `-Xelide-below` |
|||
* is greater than `ASSERTION`. |
|||
* |
|||
* @see [[scala.annotation.elidable elidable]] |
|||
* @param assertion the expression to test |
|||
* @group assertions |
|||
*/ |
|||
@elidable(ASSERTION) |
|||
def assert(assertion: Boolean): Unit = { |
|||
if (!assertion) |
|||
throw new java.lang.AssertionError("assertion failed") |
|||
} |
|||
|
|||
/** Tests an expression, throwing an `AssertionError` if false. |
|||
* Calls to this method will not be generated if `-Xelide-below` |
|||
* is greater than `ASSERTION`. |
|||
* |
|||
* @see [[scala.annotation.elidable elidable]] |
|||
* @param assertion the expression to test |
|||
* @param message a String to include in the failure message |
|||
* @group assertions |
|||
*/ |
|||
@elidable(ASSERTION) @inline |
|||
final def assert(assertion: Boolean, message: => Any): Unit = { |
|||
if (!assertion) |
|||
throw new java.lang.AssertionError("assertion failed: "+ message) |
|||
} |
|||
|
|||
/** Tests an expression, throwing an `AssertionError` if false. |
|||
* This method differs from assert only in the intent expressed: |
|||
* assert contains a predicate which needs to be proven, while |
|||
* assume contains an axiom for a static checker. Calls to this method |
|||
* will not be generated if `-Xelide-below` is greater than `ASSERTION`. |
|||
* |
|||
* @see [[scala.annotation.elidable elidable]] |
|||
* @param assumption the expression to test |
|||
* @group assertions |
|||
*/ |
|||
@elidable(ASSERTION) |
|||
def assume(assumption: Boolean): Unit = { |
|||
if (!assumption) |
|||
throw new java.lang.AssertionError("assumption failed") |
|||
} |
|||
|
|||
/** Tests an expression, throwing an `AssertionError` if false. |
|||
* This method differs from assert only in the intent expressed: |
|||
* assert contains a predicate which needs to be proven, while |
|||
* assume contains an axiom for a static checker. Calls to this method |
|||
* will not be generated if `-Xelide-below` is greater than `ASSERTION`. |
|||
* |
|||
* @see [[scala.annotation.elidable elidable]] |
|||
* @param assumption the expression to test |
|||
* @param message a String to include in the failure message |
|||
* @group assertions |
|||
*/ |
|||
@elidable(ASSERTION) @inline |
|||
final def assume(assumption: Boolean, message: => Any): Unit = { |
|||
if (!assumption) |
|||
throw new java.lang.AssertionError("assumption failed: "+ message) |
|||
} |
|||
|
|||
/** Tests an expression, throwing an `IllegalArgumentException` if false. |
|||
* This method is similar to `assert`, but blames the caller of the method |
|||
* for violating the condition. |
|||
* |
|||
* @param requirement the expression to test |
|||
* @group assertions |
|||
*/ |
|||
def require(requirement: Boolean): Unit = { |
|||
if (!requirement) |
|||
throw new IllegalArgumentException("requirement failed") |
|||
} |
|||
|
|||
/** Tests an expression, throwing an `IllegalArgumentException` if false. |
|||
* This method is similar to `assert`, but blames the caller of the method |
|||
* for violating the condition. |
|||
* |
|||
* @param requirement the expression to test |
|||
* @param message a String to include in the failure message |
|||
* @group assertions |
|||
*/ |
|||
@inline final def require(requirement: Boolean, message: => Any): Unit = { |
|||
if (!requirement) |
|||
throw new IllegalArgumentException("requirement failed: "+ message) |
|||
} |
|||
|
|||
/** `???` can be used for marking methods that remain to be implemented. |
|||
* @throws NotImplementedError when `???` is invoked. |
|||
* @group utilities |
|||
*/ |
|||
def ??? : Nothing = throw new NotImplementedError |
|||
|
|||
// implicit classes ----------------------------------------------------- |
|||
|
|||
/** @group implicit-classes-any */ |
|||
implicit final class ArrowAssoc[A](private val self: A) extends AnyVal { |
|||
@inline def -> [B](y: B): (A, B) = (self, y) |
|||
@deprecated("Use `->` instead. If you still wish to display it as one character, consider using a font with programming ligatures such as Fira Code.", "2.13.0") |
|||
def →[B](y: B): (A, B) = ->(y) |
|||
} |
|||
|
|||
/** @group implicit-classes-any */ |
|||
implicit final class Ensuring[A](private val self: A) extends AnyVal { |
|||
def ensuring(cond: Boolean): A = { assert(cond); self } |
|||
def ensuring(cond: Boolean, msg: => Any): A = { assert(cond, msg); self } |
|||
def ensuring(cond: A => Boolean): A = { assert(cond(self)); self } |
|||
def ensuring(cond: A => Boolean, msg: => Any): A = { assert(cond(self), msg); self } |
|||
} |
|||
|
|||
/** @group implicit-classes-any */ |
|||
implicit final class StringFormat[A](private val self: A) extends AnyVal { |
|||
/** Returns string formatted according to given `format` string. |
|||
* Format strings are as for `String.format` |
|||
* (@see java.lang.String.format). |
|||
*/ |
|||
@inline def formatted(fmtstr: String): String = fmtstr format self |
|||
} |
|||
|
|||
/** Injects String concatenation operator `+` to any classes. |
|||
* @group implicit-classes-any |
|||
*/ |
|||
@(deprecated @companionMethod)("Implicit injection of + is deprecated. Convert to String to call +", "2.13.0") |
|||
@(deprecated @companionClass)("Implicit injection of + is deprecated. Convert to String to call +", "2.13.0") // for Scaladoc |
|||
// scala/bug#8229 retaining the pre 2.11 name for source compatibility in shadowing this implicit |
|||
implicit final class any2stringadd[A](private val self: A) extends AnyVal { |
|||
def +(other: String): String = String.valueOf(self) + other |
|||
} |
|||
|
|||
implicit final class SeqCharSequence(sequenceOfChars: scala.collection.IndexedSeq[Char]) extends CharSequence { |
|||
def length: Int = sequenceOfChars.length |
|||
def charAt(index: Int): Char = sequenceOfChars(index) |
|||
def subSequence(start: Int, end: Int): CharSequence = new SeqCharSequence(sequenceOfChars.slice(start, end)) |
|||
override def toString = sequenceOfChars.mkString |
|||
} |
|||
|
|||
/** @group implicit-classes-char */ |
|||
implicit final class ArrayCharSequence(arrayOfChars: Array[Char]) extends CharSequence { |
|||
def length: Int = arrayOfChars.length |
|||
def charAt(index: Int): Char = arrayOfChars(index) |
|||
def subSequence(start: Int, end: Int): CharSequence = new runtime.ArrayCharSequence(arrayOfChars, start, end) |
|||
override def toString = arrayOfChars.mkString |
|||
} |
|||
|
|||
/** @group conversions-string */ |
|||
@inline implicit def augmentString(x: String): StringOps = new StringOps(x) |
|||
|
|||
// printing ----------------------------------------------------------- |
|||
|
|||
/** Prints an object to `out` using its `toString` method. |
|||
* |
|||
* @param x the object to print; may be null. |
|||
* @group console-output |
|||
*/ |
|||
def print(x: Any): Unit = Console.print(x) |
|||
|
|||
/** Prints a newline character on the default output. |
|||
* @group console-output |
|||
*/ |
|||
def println(): Unit = Console.println() |
|||
|
|||
/** Prints out an object to the default output, followed by a newline character. |
|||
* |
|||
* @param x the object to print. |
|||
* @group console-output |
|||
*/ |
|||
def println(x: Any): Unit = Console.println(x) |
|||
|
|||
/** Prints its arguments as a formatted string to the default output, |
|||
* based on a string pattern (in a fashion similar to printf in C). |
|||
* |
|||
* The interpretation of the formatting patterns is described in |
|||
* [[java.util.Formatter]]. |
|||
* |
|||
* Consider using the [[scala.StringContext.f f interpolator]] as more type safe and idiomatic. |
|||
* |
|||
* @param text the pattern for formatting the arguments. |
|||
* @param xs the arguments used to instantiate the pattern. |
|||
* @throws java.lang.IllegalArgumentException if there was a problem with the format string or arguments |
|||
* |
|||
* @see [[scala.StringContext.f StringContext.f]] |
|||
* @group console-output |
|||
*/ |
|||
def printf(text: String, xs: Any*): Unit = Console.print(text.format(xs: _*)) |
|||
|
|||
// views -------------------------------------------------------------- |
|||
|
|||
// these two are morally deprecated but the @deprecated annotation has been moved to the extension method themselves, |
|||
// in order to provide a more specific deprecation method. |
|||
implicit def tuple2ToZippedOps[T1, T2](x: (T1, T2)): runtime.Tuple2Zipped.Ops[T1, T2] = new runtime.Tuple2Zipped.Ops(x) |
|||
implicit def tuple3ToZippedOps[T1, T2, T3](x: (T1, T2, T3)): runtime.Tuple3Zipped.Ops[T1, T2, T3] = new runtime.Tuple3Zipped.Ops(x) |
|||
|
|||
// Not specialized anymore since 2.13 but we still need separate methods |
|||
// to avoid https://github.com/scala/bug/issues/10746 |
|||
// TODO: should not need @inline. add heuristic to inline factories for value classes. |
|||
@inline implicit def genericArrayOps[T](xs: Array[T]): ArrayOps[T] = new ArrayOps(xs) |
|||
@inline implicit def booleanArrayOps(xs: Array[Boolean]): ArrayOps[Boolean] = new ArrayOps(xs) |
|||
@inline implicit def byteArrayOps(xs: Array[Byte]): ArrayOps[Byte] = new ArrayOps(xs) |
|||
@inline implicit def charArrayOps(xs: Array[Char]): ArrayOps[Char] = new ArrayOps(xs) |
|||
@inline implicit def doubleArrayOps(xs: Array[Double]): ArrayOps[Double] = new ArrayOps(xs) |
|||
@inline implicit def floatArrayOps(xs: Array[Float]): ArrayOps[Float] = new ArrayOps(xs) |
|||
@inline implicit def intArrayOps(xs: Array[Int]): ArrayOps[Int] = new ArrayOps(xs) |
|||
@inline implicit def longArrayOps(xs: Array[Long]): ArrayOps[Long] = new ArrayOps(xs) |
|||
@inline implicit def refArrayOps[T <: AnyRef](xs: Array[T]): ArrayOps[T] = new ArrayOps(xs) |
|||
@inline implicit def shortArrayOps(xs: Array[Short]): ArrayOps[Short] = new ArrayOps(xs) |
|||
@inline implicit def unitArrayOps(xs: Array[Unit]): ArrayOps[Unit] = new ArrayOps(xs) |
|||
|
|||
// "Autoboxing" and "Autounboxing" --------------------------------------------------- |
|||
|
|||
/** @group conversions-anyval-to-java */ |
|||
implicit def byte2Byte(x: Byte): java.lang.Byte = x.asInstanceOf[java.lang.Byte] |
|||
/** @group conversions-anyval-to-java */ |
|||
implicit def short2Short(x: Short): java.lang.Short = x.asInstanceOf[java.lang.Short] |
|||
/** @group conversions-anyval-to-java */ |
|||
implicit def char2Character(x: Char): java.lang.Character = x.asInstanceOf[java.lang.Character] |
|||
/** @group conversions-anyval-to-java */ |
|||
implicit def int2Integer(x: Int): java.lang.Integer = x.asInstanceOf[java.lang.Integer] |
|||
/** @group conversions-anyval-to-java */ |
|||
implicit def long2Long(x: Long): java.lang.Long = x.asInstanceOf[java.lang.Long] |
|||
/** @group conversions-anyval-to-java */ |
|||
implicit def float2Float(x: Float): java.lang.Float = x.asInstanceOf[java.lang.Float] |
|||
/** @group conversions-anyval-to-java */ |
|||
implicit def double2Double(x: Double): java.lang.Double = x.asInstanceOf[java.lang.Double] |
|||
/** @group conversions-anyval-to-java */ |
|||
implicit def boolean2Boolean(x: Boolean): java.lang.Boolean = x.asInstanceOf[java.lang.Boolean] |
|||
|
|||
/** @group conversions-java-to-anyval */ |
|||
implicit def Byte2byte(x: java.lang.Byte): Byte = x.asInstanceOf[Byte] |
|||
/** @group conversions-java-to-anyval */ |
|||
implicit def Short2short(x: java.lang.Short): Short = x.asInstanceOf[Short] |
|||
/** @group conversions-java-to-anyval */ |
|||
implicit def Character2char(x: java.lang.Character): Char = x.asInstanceOf[Char] |
|||
/** @group conversions-java-to-anyval */ |
|||
implicit def Integer2int(x: java.lang.Integer): Int = x.asInstanceOf[Int] |
|||
/** @group conversions-java-to-anyval */ |
|||
implicit def Long2long(x: java.lang.Long): Long = x.asInstanceOf[Long] |
|||
/** @group conversions-java-to-anyval */ |
|||
implicit def Float2float(x: java.lang.Float): Float = x.asInstanceOf[Float] |
|||
/** @group conversions-java-to-anyval */ |
|||
implicit def Double2double(x: java.lang.Double): Double = x.asInstanceOf[Double] |
|||
/** @group conversions-java-to-anyval */ |
|||
implicit def Boolean2boolean(x: java.lang.Boolean): Boolean = x.asInstanceOf[Boolean] |
|||
|
|||
/** An implicit of type `A => A` is available for all `A` because it can always |
|||
* be implemented using the identity function. This also means that an |
|||
* implicit of type `A => B` is always available when `A <: B`, because |
|||
* `(A => A) <: (A => B)`. |
|||
*/ |
|||
// $ to avoid accidental shadowing (e.g. scala/bug#7788) |
|||
implicit def $conforms[A]: A => A = <:<.refl |
|||
} |
|||
|
|||
/** The `LowPriorityImplicits` class provides implicit values that |
|||
* are valid in all Scala compilation units without explicit qualification, |
|||
* but that are partially overridden by higher-priority conversions in object |
|||
* `Predef`. |
|||
*/ |
|||
// scala/bug#7335 Parents of Predef are defined in the same compilation unit to avoid |
|||
// cyclic reference errors compiling the standard library *without* a previously |
|||
// compiled copy on the classpath. |
|||
private[scala] abstract class LowPriorityImplicits extends LowPriorityImplicits2 { |
|||
import mutable.ArraySeq |
|||
|
|||
/** We prefer the java.lang.* boxed types to these wrappers in |
|||
* any potential conflicts. Conflicts do exist because the wrappers |
|||
* need to implement ScalaNumber in order to have a symmetric equals |
|||
* method, but that implies implementing java.lang.Number as well. |
|||
* |
|||
* Note - these are inlined because they are value classes, but |
|||
* the call to xxxWrapper is not eliminated even though it does nothing. |
|||
* Even inlined, every call site does a no-op retrieval of Predef's MODULE$ |
|||
* because maybe loading Predef has side effects! |
|||
*/ |
|||
@inline implicit def byteWrapper(x: Byte): runtime.RichByte = new runtime.RichByte(x) |
|||
@inline implicit def shortWrapper(x: Short): runtime.RichShort = new runtime.RichShort(x) |
|||
@inline implicit def intWrapper(x: Int): runtime.RichInt = new runtime.RichInt(x) |
|||
@inline implicit def charWrapper(c: Char): runtime.RichChar = new runtime.RichChar(c) |
|||
@inline implicit def longWrapper(x: Long): runtime.RichLong = new runtime.RichLong(x) |
|||
@inline implicit def floatWrapper(x: Float): runtime.RichFloat = new runtime.RichFloat(x) |
|||
@inline implicit def doubleWrapper(x: Double): runtime.RichDouble = new runtime.RichDouble(x) |
|||
@inline implicit def booleanWrapper(x: Boolean): runtime.RichBoolean = new runtime.RichBoolean(x) |
|||
|
|||
/** @group conversions-array-to-wrapped-array */ |
|||
implicit def genericWrapArray[T](xs: Array[T]): ArraySeq[T] = |
|||
if (xs eq null) null |
|||
else ArraySeq.make(xs) |
|||
|
|||
// Since the JVM thinks arrays are covariant, one 0-length Array[AnyRef] |
|||
// is as good as another for all T <: AnyRef. Instead of creating 100,000,000 |
|||
// unique ones by way of this implicit, let's share one. |
|||
/** @group conversions-array-to-wrapped-array */ |
|||
implicit def wrapRefArray[T <: AnyRef](xs: Array[T]): ArraySeq.ofRef[T] = { |
|||
if (xs eq null) null |
|||
else if (xs.length == 0) ArraySeq.empty[AnyRef].asInstanceOf[ArraySeq.ofRef[T]] |
|||
else new ArraySeq.ofRef[T](xs) |
|||
} |
|||
|
|||
/** @group conversions-array-to-wrapped-array */ |
|||
implicit def wrapIntArray(xs: Array[Int]): ArraySeq.ofInt = if (xs ne null) new ArraySeq.ofInt(xs) else null |
|||
/** @group conversions-array-to-wrapped-array */ |
|||
implicit def wrapDoubleArray(xs: Array[Double]): ArraySeq.ofDouble = if (xs ne null) new ArraySeq.ofDouble(xs) else null |
|||
/** @group conversions-array-to-wrapped-array */ |
|||
implicit def wrapLongArray(xs: Array[Long]): ArraySeq.ofLong = if (xs ne null) new ArraySeq.ofLong(xs) else null |
|||
/** @group conversions-array-to-wrapped-array */ |
|||
implicit def wrapFloatArray(xs: Array[Float]): ArraySeq.ofFloat = if (xs ne null) new ArraySeq.ofFloat(xs) else null |
|||
/** @group conversions-array-to-wrapped-array */ |
|||
implicit def wrapCharArray(xs: Array[Char]): ArraySeq.ofChar = if (xs ne null) new ArraySeq.ofChar(xs) else null |
|||
/** @group conversions-array-to-wrapped-array */ |
|||
implicit def wrapByteArray(xs: Array[Byte]): ArraySeq.ofByte = if (xs ne null) new ArraySeq.ofByte(xs) else null |
|||
/** @group conversions-array-to-wrapped-array */ |
|||
implicit def wrapShortArray(xs: Array[Short]): ArraySeq.ofShort = if (xs ne null) new ArraySeq.ofShort(xs) else null |
|||
/** @group conversions-array-to-wrapped-array */ |
|||
implicit def wrapBooleanArray(xs: Array[Boolean]): ArraySeq.ofBoolean = if (xs ne null) new ArraySeq.ofBoolean(xs) else null |
|||
/** @group conversions-array-to-wrapped-array */ |
|||
implicit def wrapUnitArray(xs: Array[Unit]): ArraySeq.ofUnit = if (xs ne null) new ArraySeq.ofUnit(xs) else null |
|||
|
|||
/** @group conversions-string */ |
|||
implicit def wrapString(s: String): WrappedString = if (s ne null) new WrappedString(s) else null |
|||
} |
|||
|
|||
private[scala] abstract class LowPriorityImplicits2 { |
|||
@deprecated("Implicit conversions from Array to immutable.IndexedSeq are implemented by copying; Use the more efficient non-copying ArraySeq.unsafeWrapArray or an explicit toIndexedSeq call", "2.13.0") |
|||
implicit def copyArrayToImmutableIndexedSeq[T](xs: Array[T]): IndexedSeq[T] = |
|||
if (xs eq null) null |
|||
else new ArrayOps(xs).toIndexedSeq |
|||
} |
@ -0,0 +1,33 @@ |
|||
/* |
|||
* Scala (https://www.scala-lang.org) |
|||
* |
|||
* Copyright EPFL and Lightbend, Inc. |
|||
* |
|||
* Licensed under Apache License 2.0 |
|||
* (http://www.apache.org/licenses/LICENSE-2.0). |
|||
* |
|||
* See the NOTICE file distributed with this work for |
|||
* additional information regarding copyright ownership. |
|||
*/ |
|||
|
|||
package scala.annotation |
|||
|
|||
/** An annotation to be applied to a match expression. If present, |
|||
* the compiler will verify that the match has been compiled to a |
|||
* [[http://docs.oracle.com/javase/specs/jvms/se7/html/jvms-3.html#jvms-3.10 tableswitch or lookupswitch]] |
|||
* and issue a warning if it instead compiles into a series of conditional expressions. |
|||
* Example usage: |
|||
{{{ |
|||
val Constant = 'Q' |
|||
def tokenMe(ch: Char) = (ch: @switch) match { |
|||
case ' ' | '\t' | '\n' => 1 |
|||
case 'A' | 'Z' | '$' => 2 |
|||
case '5' | Constant => 3 // a non-literal may prevent switch generation: this would not compile |
|||
case _ => 4 |
|||
} |
|||
}}} |
|||
* |
|||
* Note: for pattern matches with one or two cases, the compiler generates jump instructions. |
|||
* Annotating such a match with `@switch` does not issue any warning. |
|||
*/ |
|||
final class switch extends scala.annotation.StaticAnnotation |
File diff suppressed because it is too large
File diff suppressed because it is too large
@ -0,0 +1,288 @@ |
|||
/* |
|||
* Scala (https://www.scala-lang.org) |
|||
* |
|||
* Copyright EPFL and Lightbend, Inc. |
|||
* |
|||
* Licensed under Apache License 2.0 |
|||
* (http://www.apache.org/licenses/LICENSE-2.0). |
|||
* |
|||
* See the NOTICE file distributed with this work for |
|||
* additional information regarding copyright ownership. |
|||
*/ |
|||
|
|||
package scala |
|||
package collection |
|||
|
|||
import scala.annotation.tailrec |
|||
|
|||
/** Base trait for linearly accessed sequences that have efficient `head` and |
|||
* `tail` operations. |
|||
* Known subclasses: List, LazyList |
|||
*/ |
|||
trait LinearSeq[+A] extends Seq[A] |
|||
with LinearSeqOps[A, LinearSeq, LinearSeq[A]] |
|||
with IterableFactoryDefaults[A, LinearSeq] { |
|||
override protected[this] def stringPrefix: String = "LinearSeq" |
|||
|
|||
override def iterableFactory: SeqFactory[LinearSeq] = LinearSeq |
|||
} |
|||
|
|||
@SerialVersionUID(3L) |
|||
object LinearSeq extends SeqFactory.Delegate[LinearSeq](immutable.LinearSeq) |
|||
|
|||
/** Base trait for linear Seq operations */ |
|||
trait LinearSeqOps[+A, +CC[X] <: LinearSeq[X], +C <: LinearSeq[A] with LinearSeqOps[A, CC, C]] extends Any with SeqOps[A, CC, C] { |
|||
|
|||
// To be overridden in implementations: |
|||
def isEmpty: Boolean |
|||
def head: A |
|||
def tail: C |
|||
|
|||
override def headOption: Option[A] = |
|||
if (isEmpty) None else Some(head) |
|||
|
|||
def iterator: Iterator[A] = |
|||
if (knownSize == 0) Iterator.empty |
|||
else new LinearSeqIterator[A](this) |
|||
|
|||
def length: Int = { |
|||
var these = coll |
|||
var len = 0 |
|||
while (these.nonEmpty) { |
|||
len += 1 |
|||
these = these.tail |
|||
} |
|||
len |
|||
} |
|||
|
|||
override def last: A = { |
|||
if (isEmpty) throw new NoSuchElementException("LinearSeq.last") |
|||
else { |
|||
var these = coll |
|||
var scout = tail |
|||
while (scout.nonEmpty) { |
|||
these = scout |
|||
scout = scout.tail |
|||
} |
|||
these.head |
|||
} |
|||
} |
|||
|
|||
override def lengthCompare(len: Int): Int = { |
|||
@tailrec def loop(i: Int, xs: LinearSeq[A]): Int = { |
|||
if (i == len) |
|||
if (xs.isEmpty) 0 else 1 |
|||
else if (xs.isEmpty) |
|||
-1 |
|||
else |
|||
loop(i + 1, xs.tail) |
|||
} |
|||
if (len < 0) 1 |
|||
else loop(0, coll) |
|||
} |
|||
|
|||
override def lengthCompare(that: Iterable[_]): Int = { |
|||
val thatKnownSize = that.knownSize |
|||
|
|||
if (thatKnownSize >= 0) this lengthCompare thatKnownSize |
|||
else that match { |
|||
case that: LinearSeq[_] => |
|||
var thisSeq = this |
|||
var thatSeq = that |
|||
while (thisSeq.nonEmpty && thatSeq.nonEmpty) { |
|||
thisSeq = thisSeq.tail |
|||
thatSeq = thatSeq.tail |
|||
} |
|||
java.lang.Boolean.compare(thisSeq.nonEmpty, thatSeq.nonEmpty) |
|||
case _ => |
|||
var thisSeq = this |
|||
val thatIt = that.iterator |
|||
while (thisSeq.nonEmpty && thatIt.hasNext) { |
|||
thisSeq = thisSeq.tail |
|||
thatIt.next() |
|||
} |
|||
java.lang.Boolean.compare(thisSeq.nonEmpty, thatIt.hasNext) |
|||
} |
|||
} |
|||
|
|||
override def isDefinedAt(x: Int): Boolean = x >= 0 && lengthCompare(x) > 0 |
|||
|
|||
// `apply` is defined in terms of `drop`, which is in turn defined in |
|||
// terms of `tail`. |
|||
@throws[IndexOutOfBoundsException] |
|||
override def apply(n: Int): A = { |
|||
if (n < 0) throw new IndexOutOfBoundsException(n.toString) |
|||
val skipped = drop(n) |
|||
if (skipped.isEmpty) throw new IndexOutOfBoundsException(n.toString) |
|||
skipped.head |
|||
} |
|||
|
|||
override def foreach[U](f: A => U): Unit = { |
|||
var these: LinearSeq[A] = coll |
|||
while (!these.isEmpty) { |
|||
f(these.head) |
|||
these = these.tail |
|||
} |
|||
} |
|||
|
|||
override def forall(p: A => Boolean): Boolean = { |
|||
var these: LinearSeq[A] = coll |
|||
while (!these.isEmpty) { |
|||
if (!p(these.head)) return false |
|||
these = these.tail |
|||
} |
|||
true |
|||
} |
|||
|
|||
override def exists(p: A => Boolean): Boolean = { |
|||
var these: LinearSeq[A] = coll |
|||
while (!these.isEmpty) { |
|||
if (p(these.head)) return true |
|||
these = these.tail |
|||
} |
|||
false |
|||
} |
|||
|
|||
override def contains[A1 >: A](elem: A1): Boolean = { |
|||
var these: LinearSeq[A] = coll |
|||
while (!these.isEmpty) { |
|||
if (these.head == elem) return true |
|||
these = these.tail |
|||
} |
|||
false |
|||
} |
|||
|
|||
override def find(p: A => Boolean): Option[A] = { |
|||
var these: LinearSeq[A] = coll |
|||
while (!these.isEmpty) { |
|||
if (p(these.head)) return Some(these.head) |
|||
these = these.tail |
|||
} |
|||
None |
|||
} |
|||
|
|||
override def foldLeft[B](z: B)(op: (B, A) => B): B = { |
|||
var acc = z |
|||
var these: LinearSeq[A] = coll |
|||
while (!these.isEmpty) { |
|||
acc = op(acc, these.head) |
|||
these = these.tail |
|||
} |
|||
acc |
|||
} |
|||
|
|||
override def sameElements[B >: A](that: IterableOnce[B]): Boolean = { |
|||
@tailrec def linearSeqEq(a: LinearSeq[B], b: LinearSeq[B]): Boolean = |
|||
(a eq b) || { |
|||
if (a.nonEmpty && b.nonEmpty && a.head == b.head) { |
|||
linearSeqEq(a.tail, b.tail) |
|||
} |
|||
else { |
|||
a.isEmpty && b.isEmpty |
|||
} |
|||
} |
|||
|
|||
that match { |
|||
case that: LinearSeq[B] => linearSeqEq(coll, that) |
|||
case _ => super.sameElements(that) |
|||
} |
|||
} |
|||
|
|||
override def segmentLength(p: A => Boolean, from: Int): Int = { |
|||
var i = 0 |
|||
var seq = drop(from) |
|||
while (seq.nonEmpty && p(seq.head)) { |
|||
i += 1 |
|||
seq = seq.tail |
|||
} |
|||
i |
|||
} |
|||
|
|||
override def indexWhere(p: A => Boolean, from: Int): Int = { |
|||
var i = math.max(from, 0) |
|||
var these: LinearSeq[A] = this drop from |
|||
while (these.nonEmpty) { |
|||
if (p(these.head)) |
|||
return i |
|||
|
|||
i += 1 |
|||
these = these.tail |
|||
} |
|||
-1 |
|||
} |
|||
|
|||
override def lastIndexWhere(p: A => Boolean, end: Int): Int = { |
|||
var i = 0 |
|||
var these: LinearSeq[A] = coll |
|||
var last = -1 |
|||
while (!these.isEmpty && i <= end) { |
|||
if (p(these.head)) last = i |
|||
these = these.tail |
|||
i += 1 |
|||
} |
|||
last |
|||
} |
|||
|
|||
override def findLast(p: A => Boolean): Option[A] = { |
|||
var these: LinearSeq[A] = coll |
|||
var found = false |
|||
var last: A = null.asInstanceOf[A] // don't use `Option`, to prevent excessive `Some` allocation |
|||
while (these.nonEmpty) { |
|||
val elem = these.head |
|||
if (p(elem)) { |
|||
found = true |
|||
last = elem |
|||
} |
|||
these = these.tail |
|||
} |
|||
if (found) Some(last) else None |
|||
} |
|||
|
|||
override def tails: Iterator[C] = |
|||
Iterator.iterate(coll)(_.tail).takeWhile(_.nonEmpty) ++ Iterator.single(newSpecificBuilder.result()) |
|||
} |
|||
|
|||
trait StrictOptimizedLinearSeqOps[+A, +CC[X] <: LinearSeq[X], +C <: LinearSeq[A] with StrictOptimizedLinearSeqOps[A, CC, C]] extends Any with LinearSeqOps[A, CC, C] with StrictOptimizedSeqOps[A, CC, C] { |
|||
// A more efficient iterator implementation than the default LinearSeqIterator |
|||
override def iterator: Iterator[A] = new AbstractIterator[A] { |
|||
private[this] var current: Iterable[A] = toIterable |
|||
def hasNext = !current.isEmpty |
|||
def next() = { val r = current.head; current = current.tail; r } |
|||
} |
|||
|
|||
// Optimized version of `drop` that avoids copying |
|||
override def drop(n: Int): C = { |
|||
@tailrec def loop(n: Int, s: C): C = |
|||
if (n <= 0 || s.isEmpty) s |
|||
else loop(n - 1, s.tail) |
|||
loop(n, coll) |
|||
} |
|||
|
|||
override def dropWhile(p: A => Boolean): C = { |
|||
@tailrec def loop(s: C): C = |
|||
if (s.nonEmpty && p(s.head)) loop(s.tail) |
|||
else s |
|||
loop(coll) |
|||
} |
|||
} |
|||
|
|||
/** A specialized Iterator for LinearSeqs that is lazy enough for Stream and LazyList. This is accomplished by not |
|||
* evaluating the tail after returning the current head. |
|||
*/ |
|||
private[collection] final class LinearSeqIterator[A](coll: LinearSeqOps[A, LinearSeq, LinearSeq[A]]) extends AbstractIterator[A] { |
|||
// A call-by-need cell |
|||
private[this] final class LazyCell(st: => LinearSeqOps[A, LinearSeq, LinearSeq[A]]) { lazy val v = st } |
|||
|
|||
private[this] var these: LazyCell = new LazyCell(coll) |
|||
|
|||
def hasNext: Boolean = these.v.nonEmpty |
|||
|
|||
def next(): A = |
|||
if (isEmpty) Iterator.empty.next() |
|||
else { |
|||
val cur = these.v |
|||
val result = cur.head |
|||
these = new LazyCell(cur.tail) |
|||
result |
|||
} |
|||
} |
@ -0,0 +1,659 @@ |
|||
/* |
|||
* Scala (https://www.scala-lang.org) |
|||
* |
|||
* Copyright EPFL and Lightbend, Inc. |
|||
* |
|||
* Licensed under Apache License 2.0 |
|||
* (http://www.apache.org/licenses/LICENSE-2.0). |
|||
* |
|||
* See the NOTICE file distributed with this work for |
|||
* additional information regarding copyright ownership. |
|||
*/ |
|||
|
|||
package scala |
|||
package collection |
|||
package immutable |
|||
|
|||
import scala.annotation.unchecked.uncheckedVariance |
|||
import scala.annotation.tailrec |
|||
import mutable.{Builder, ListBuffer} |
|||
import scala.collection.generic.DefaultSerializable |
|||
import scala.runtime.Statics.releaseFence |
|||
|
|||
/** A class for immutable linked lists representing ordered collections |
|||
* of elements of type `A`. |
|||
* |
|||
* This class comes with two implementing case classes `scala.Nil` |
|||
* and `scala.::` that implement the abstract members `isEmpty`, |
|||
* `head` and `tail`. |
|||
* |
|||
* This class is optimal for last-in-first-out (LIFO), stack-like access patterns. If you need another access |
|||
* pattern, for example, random access or FIFO, consider using a collection more suited to this than `List`. |
|||
* |
|||
* ==Performance== |
|||
* '''Time:''' `List` has `O(1)` prepend and head/tail access. Most other operations are `O(n)` on the number of elements in the list. |
|||
* This includes the index-based lookup of elements, `length`, `append` and `reverse`. |
|||
* |
|||
* '''Space:''' `List` implements '''structural sharing''' of the tail list. This means that many operations are either |
|||
* zero- or constant-memory cost. |
|||
* {{{ |
|||
* val mainList = List(3, 2, 1) |
|||
* val with4 = 4 :: mainList // re-uses mainList, costs one :: instance |
|||
* val with42 = 42 :: mainList // also re-uses mainList, cost one :: instance |
|||
* val shorter = mainList.tail // costs nothing as it uses the same 2::1::Nil instances as mainList |
|||
* }}} |
|||
* |
|||
* @example {{{ |
|||
* // Make a list via the companion object factory |
|||
* val days = List("Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday") |
|||
* |
|||
* // Make a list element-by-element |
|||
* val when = "AM" :: "PM" :: Nil |
|||
* |
|||
* // Pattern match |
|||
* days match { |
|||
* case firstDay :: otherDays => |
|||
* println("The first day of the week is: " + firstDay) |
|||
* case Nil => |
|||
* println("There don't seem to be any week days.") |
|||
* } |
|||
* }}} |
|||
* |
|||
* @note The functional list is characterized by persistence and structural sharing, thus offering considerable |
|||
* performance and space consumption benefits in some scenarios if used correctly. |
|||
* However, note that objects having multiple references into the same functional list (that is, |
|||
* objects that rely on structural sharing), will be serialized and deserialized with multiple lists, one for |
|||
* each reference to it. I.e. structural sharing is lost after serialization/deserialization. |
|||
* |
|||
* @see [[http://docs.scala-lang.org/overviews/collections/concrete-immutable-collection-classes.html#lists "Scala's Collection Library overview"]] |
|||
* section on `Lists` for more information. |
|||
* |
|||
* @define coll list |
|||
* @define Coll `List` |
|||
* @define orderDependent |
|||
* @define orderDependentFold |
|||
* @define mayNotTerminateInf |
|||
* @define willNotTerminateInf |
|||
*/ |
|||
@SerialVersionUID(3L) |
|||
sealed abstract class List[+A] |
|||
extends AbstractSeq[A] |
|||
with LinearSeq[A] |
|||
with LinearSeqOps[A, List, List[A]] |
|||
with StrictOptimizedLinearSeqOps[A, List, List[A]] |
|||
with StrictOptimizedSeqOps[A, List, List[A]] |
|||
with IterableFactoryDefaults[A, List] |
|||
with DefaultSerializable { |
|||
|
|||
override def iterableFactory: SeqFactory[List] = List |
|||
|
|||
/** Adds an element at the beginning of this list. |
|||
* @param elem the element to prepend. |
|||
* @return a list which contains `x` as first element and |
|||
* which continues with this list. |
|||
* Example: |
|||
* {{{1 :: List(2, 3) = List(2, 3).::(1) = List(1, 2, 3)}}} |
|||
*/ |
|||
def :: [B >: A](elem: B): List[B] = new ::(elem, this) |
|||
|
|||
/** Adds the elements of a given list in front of this list. |
|||
* |
|||
* Example: |
|||
* {{{List(1, 2) ::: List(3, 4) = List(3, 4).:::(List(1, 2)) = List(1, 2, 3, 4)}}} |
|||
* |
|||
* @param prefix The list elements to prepend. |
|||
* @return a list resulting from the concatenation of the given |
|||
* list `prefix` and this list. |
|||
*/ |
|||
def ::: [B >: A](prefix: List[B]): List[B] = |
|||
if (isEmpty) prefix |
|||
else if (prefix.isEmpty) this |
|||
else { |
|||
val result = new ::[B](prefix.head, this) |
|||
var curr = result |
|||
var that = prefix.tail |
|||
while (!that.isEmpty) { |
|||
val temp = new ::[B](that.head, this) |
|||
curr.next = temp |
|||
curr = temp |
|||
that = that.tail |
|||
} |
|||
releaseFence() |
|||
result |
|||
} |
|||
|
|||
/** Adds the elements of a given list in reverse order in front of this list. |
|||
* `xs reverse_::: ys` is equivalent to |
|||
* `xs.reverse ::: ys` but is more efficient. |
|||
* |
|||
* @param prefix the prefix to reverse and then prepend |
|||
* @return the concatenation of the reversed prefix and the current list. |
|||
*/ |
|||
def reverse_:::[B >: A](prefix: List[B]): List[B] = { |
|||
var these: List[B] = this |
|||
var pres = prefix |
|||
while (!pres.isEmpty) { |
|||
these = pres.head :: these |
|||
pres = pres.tail |
|||
} |
|||
these |
|||
} |
|||
|
|||
override final def isEmpty: Boolean = this eq Nil |
|||
|
|||
override def prepended[B >: A](elem: B): List[B] = elem :: this |
|||
|
|||
override def prependedAll[B >: A](prefix: collection.IterableOnce[B]): List[B] = prefix match { |
|||
case xs: List[B] => xs ::: this |
|||
case _ if prefix.knownSize == 0 => this |
|||
case b: ListBuffer[B] if this.isEmpty => b.toList |
|||
case _ => |
|||
val iter = prefix.iterator |
|||
if (iter.hasNext) { |
|||
val result = new ::[B](iter.next(), this) |
|||
var curr = result |
|||
while (iter.hasNext) { |
|||
val temp = new ::[B](iter.next(), this) |
|||
curr.next = temp |
|||
curr = temp |
|||
} |
|||
releaseFence() |
|||
result |
|||
} else { |
|||
this |
|||
} |
|||
} |
|||
|
|||
// When calling appendAll with another list `suffix`, avoid copying `suffix` |
|||
override def appendedAll[B >: A](suffix: collection.IterableOnce[B]): List[B] = suffix match { |
|||
case xs: List[B] => this ::: xs |
|||
case _ => super.appendedAll(suffix) |
|||
} |
|||
|
|||
override def take(n: Int): List[A] = if (isEmpty || n <= 0) Nil else { |
|||
val h = new ::(head, Nil) |
|||
var t = h |
|||
var rest = tail |
|||
var i = 1 |
|||
while ({if (rest.isEmpty) return this; i < n}) { |
|||
i += 1 |
|||
val nx = new ::(rest.head, Nil) |
|||
t.next = nx |
|||
t = nx |
|||
rest = rest.tail |
|||
} |
|||
releaseFence() |
|||
h |
|||
} |
|||
|
|||
/** |
|||
* @example {{{ |
|||
* // Given a list |
|||
* val letters = List('a','b','c','d','e') |
|||
* |
|||
* // `slice` returns all elements beginning at index `from` and afterwards, |
|||
* // up until index `until` (excluding index `until`.) |
|||
* letters.slice(1,3) // Returns List('b','c') |
|||
* }}} |
|||
*/ |
|||
override def slice(from: Int, until: Int): List[A] = { |
|||
val lo = scala.math.max(from, 0) |
|||
if (until <= lo || isEmpty) Nil |
|||
else this drop lo take (until - lo) |
|||
} |
|||
|
|||
override def takeRight(n: Int): List[A] = { |
|||
@tailrec |
|||
def loop(lead: List[A], lag: List[A]): List[A] = lead match { |
|||
case Nil => lag |
|||
case _ :: tail => loop(tail, lag.tail) |
|||
} |
|||
loop(drop(n), this) |
|||
} |
|||
|
|||
// dropRight is inherited from LinearSeq |
|||
|
|||
override def splitAt(n: Int): (List[A], List[A]) = { |
|||
val b = new ListBuffer[A] |
|||
var i = 0 |
|||
var these = this |
|||
while (!these.isEmpty && i < n) { |
|||
i += 1 |
|||
b += these.head |
|||
these = these.tail |
|||
} |
|||
(b.toList, these) |
|||
} |
|||
|
|||
override def updated[B >: A](index: Int, elem: B): List[B] = { |
|||
var i = 0 |
|||
var current = this |
|||
val prefix = ListBuffer.empty[B] |
|||
while (i < index && current.nonEmpty) { |
|||
i += 1 |
|||
prefix += current.head |
|||
current = current.tail |
|||
} |
|||
if (i == index && current.nonEmpty) { |
|||
prefix.prependToList(elem :: current.tail) |
|||
} else { |
|||
throw new IndexOutOfBoundsException(s"$index is out of bounds (min 0, max ${length-1})") |
|||
} |
|||
} |
|||
|
|||
final override def map[B](f: A => B): List[B] = { |
|||
if (this eq Nil) Nil else { |
|||
val h = new ::[B](f(head), Nil) |
|||
var t: ::[B] = h |
|||
var rest = tail |
|||
while (rest ne Nil) { |
|||
val nx = new ::(f(rest.head), Nil) |
|||
t.next = nx |
|||
t = nx |
|||
rest = rest.tail |
|||
} |
|||
releaseFence() |
|||
h |
|||
} |
|||
} |
|||
|
|||
final override def collect[B](pf: PartialFunction[A, B]): List[B] = { |
|||
if (this eq Nil) Nil else { |
|||
var rest = this |
|||
var h: ::[B] = null |
|||
var x: Any = null |
|||
// Special case for first element |
|||
while (h eq null) { |
|||
x = pf.applyOrElse(rest.head, List.partialNotApplied) |
|||
if (x.asInstanceOf[AnyRef] ne List.partialNotApplied) h = new ::(x.asInstanceOf[B], Nil) |
|||
rest = rest.tail |
|||
if (rest eq Nil) return if (h eq null) Nil else h |
|||
} |
|||
var t = h |
|||
// Remaining elements |
|||
while (rest ne Nil) { |
|||
x = pf.applyOrElse(rest.head, List.partialNotApplied) |
|||
if (x.asInstanceOf[AnyRef] ne List.partialNotApplied) { |
|||
val nx = new ::(x.asInstanceOf[B], Nil) |
|||
t.next = nx |
|||
t = nx |
|||
} |
|||
rest = rest.tail |
|||
} |
|||
releaseFence() |
|||
h |
|||
} |
|||
} |
|||
|
|||
final override def flatMap[B](f: A => IterableOnce[B]): List[B] = { |
|||
var rest = this |
|||
var h: ::[B] = null |
|||
var t: ::[B] = null |
|||
while (rest ne Nil) { |
|||
val it = f(rest.head).iterator |
|||
while (it.hasNext) { |
|||
val nx = new ::(it.next(), Nil) |
|||
if (t eq null) { |
|||
h = nx |
|||
} else { |
|||
t.next = nx |
|||
} |
|||
t = nx |
|||
} |
|||
rest = rest.tail |
|||
} |
|||
if (h eq null) Nil else {releaseFence(); h} |
|||
} |
|||
|
|||
@inline final override def takeWhile(p: A => Boolean): List[A] = { |
|||
val b = new ListBuffer[A] |
|||
var these = this |
|||
while (!these.isEmpty && p(these.head)) { |
|||
b += these.head |
|||
these = these.tail |
|||
} |
|||
b.toList |
|||
} |
|||
|
|||
@inline final override def span(p: A => Boolean): (List[A], List[A]) = { |
|||
val b = new ListBuffer[A] |
|||
var these = this |
|||
while (!these.isEmpty && p(these.head)) { |
|||
b += these.head |
|||
these = these.tail |
|||
} |
|||
(b.toList, these) |
|||
} |
|||
|
|||
// Overridden with an implementation identical to the inherited one (at this time) |
|||
// solely so it can be finalized and thus inlinable. |
|||
@inline final override def foreach[U](f: A => U): Unit = { |
|||
var these = this |
|||
while (!these.isEmpty) { |
|||
f(these.head) |
|||
these = these.tail |
|||
} |
|||
} |
|||
|
|||
final override def reverse: List[A] = { |
|||
var result: List[A] = Nil |
|||
var these = this |
|||
while (!these.isEmpty) { |
|||
result = these.head :: result |
|||
these = these.tail |
|||
} |
|||
result |
|||
} |
|||
|
|||
final override def foldRight[B](z: B)(op: (A, B) => B): B = { |
|||
var acc = z |
|||
var these: List[A] = reverse |
|||
while (!these.isEmpty) { |
|||
acc = op(these.head, acc) |
|||
these = these.tail |
|||
} |
|||
acc |
|||
} |
|||
|
|||
// Copy/Paste overrides to avoid interface calls inside loops. |
|||
|
|||
override final def length: Int = { |
|||
var these = this |
|||
var len = 0 |
|||
while (!these.isEmpty) { |
|||
len += 1 |
|||
these = these.tail |
|||
} |
|||
len |
|||
} |
|||
|
|||
override final def lengthCompare(len: Int): Int = { |
|||
@tailrec def loop(i: Int, xs: List[A]): Int = { |
|||
if (i == len) |
|||
if (xs.isEmpty) 0 else 1 |
|||
else if (xs.isEmpty) |
|||
-1 |
|||
else |
|||
loop(i + 1, xs.tail) |
|||
} |
|||
if (len < 0) 1 |
|||
else loop(0, coll) |
|||
} |
|||
|
|||
override final def forall(p: A => Boolean): Boolean = { |
|||
var these: List[A] = this |
|||
while (!these.isEmpty) { |
|||
if (!p(these.head)) return false |
|||
these = these.tail |
|||
} |
|||
true |
|||
} |
|||
|
|||
override final def exists(p: A => Boolean): Boolean = { |
|||
var these: List[A] = this |
|||
while (!these.isEmpty) { |
|||
if (p(these.head)) return true |
|||
these = these.tail |
|||
} |
|||
false |
|||
} |
|||
|
|||
override final def contains[A1 >: A](elem: A1): Boolean = { |
|||
var these: List[A] = this |
|||
while (!these.isEmpty) { |
|||
if (these.head == elem) return true |
|||
these = these.tail |
|||
} |
|||
false |
|||
} |
|||
|
|||
override final def find(p: A => Boolean): Option[A] = { |
|||
var these: List[A] = this |
|||
while (!these.isEmpty) { |
|||
if (p(these.head)) return Some(these.head) |
|||
these = these.tail |
|||
} |
|||
None |
|||
} |
|||
|
|||
override def last: A = { |
|||
if (isEmpty) throw new NoSuchElementException("List.last") |
|||
else { |
|||
var these = this |
|||
var scout = tail |
|||
while (!scout.isEmpty) { |
|||
these = scout |
|||
scout = scout.tail |
|||
} |
|||
these.head |
|||
} |
|||
} |
|||
|
|||
override def corresponds[B](that: collection.Seq[B])(p: (A, B) => Boolean): Boolean = that match { |
|||
case that: LinearSeq[B] => |
|||
var i = this |
|||
var j = that |
|||
while (!(i.isEmpty || j.isEmpty)) { |
|||
if (!p(i.head, j.head)) |
|||
return false |
|||
i = i.tail |
|||
j = j.tail |
|||
} |
|||
i.isEmpty && j.isEmpty |
|||
case _ => |
|||
super.corresponds(that)(p) |
|||
} |
|||
|
|||
override protected[this] def className = "List" |
|||
|
|||
/** Builds a new list by applying a function to all elements of this list. |
|||
* Like `xs map f`, but returns `xs` unchanged if function |
|||
* `f` maps all elements to themselves (as determined by `eq`). |
|||
* |
|||
* @param f the function to apply to each element. |
|||
* @tparam B the element type of the returned collection. |
|||
* @return a list resulting from applying the given function |
|||
* `f` to each element of this list and collecting the results. |
|||
*/ |
|||
@`inline` final def mapConserve[B >: A <: AnyRef](f: A => B): List[B] = { |
|||
// Note to developers: there exists a duplication between this function and `reflect.internal.util.Collections#map2Conserve`. |
|||
// If any successful optimization attempts or other changes are made, please rehash them there too. |
|||
@tailrec |
|||
def loop(mappedHead: List[B], mappedLast: ::[B], unchanged: List[A], pending: List[A]): List[B] = { |
|||
if (pending.isEmpty) { |
|||
if (mappedHead eq null) unchanged |
|||
else { |
|||
mappedLast.next = (unchanged: List[B]) |
|||
mappedHead |
|||
} |
|||
} |
|||
else { |
|||
val head0 = pending.head |
|||
val head1 = f(head0) |
|||
|
|||
if (head1 eq head0.asInstanceOf[AnyRef]) |
|||
loop(mappedHead, mappedLast, unchanged, pending.tail) |
|||
else { |
|||
var xc = unchanged |
|||
var mappedHead1: List[B] = mappedHead |
|||
var mappedLast1: ::[B] = mappedLast |
|||
while (xc ne pending) { |
|||
val next = new ::[B](xc.head, Nil) |
|||
if (mappedHead1 eq null) mappedHead1 = next |
|||
if (mappedLast1 ne null) mappedLast1.next = next |
|||
mappedLast1 = next |
|||
xc = xc.tail |
|||
} |
|||
val next = new ::(head1, Nil) |
|||
if (mappedHead1 eq null) mappedHead1 = next |
|||
if (mappedLast1 ne null) mappedLast1.next = next |
|||
mappedLast1 = next |
|||
val tail0 = pending.tail |
|||
loop(mappedHead1, mappedLast1, tail0, tail0) |
|||
|
|||
} |
|||
} |
|||
} |
|||
val result = loop(null, null, this, this) |
|||
releaseFence() |
|||
result |
|||
} |
|||
|
|||
override def filter(p: A => Boolean): List[A] = filterCommon(p, isFlipped = false) |
|||
|
|||
override def filterNot(p: A => Boolean): List[A] = filterCommon(p, isFlipped = true) |
|||
|
|||
private[this] def filterCommon(p: A => Boolean, isFlipped: Boolean): List[A] = { |
|||
|
|||
// everything seen so far so far is not included |
|||
@tailrec def noneIn(l: List[A]): List[A] = { |
|||
if (l.isEmpty) |
|||
Nil |
|||
else { |
|||
val h = l.head |
|||
val t = l.tail |
|||
if (p(h) != isFlipped) |
|||
allIn(l, t) |
|||
else |
|||
noneIn(t) |
|||
} |
|||
} |
|||
|
|||
// everything from 'start' is included, if everything from this point is in we can return the origin |
|||
// start otherwise if we discover an element that is out we must create a new partial list. |
|||
@tailrec def allIn(start: List[A], remaining: List[A]): List[A] = { |
|||
if (remaining.isEmpty) |
|||
start |
|||
else { |
|||
val x = remaining.head |
|||
if (p(x) != isFlipped) |
|||
allIn(start, remaining.tail) |
|||
else |
|||
partialFill(start, remaining) |
|||
} |
|||
} |
|||
|
|||
// we have seen elements that should be included then one that should be excluded, start building |
|||
def partialFill(origStart: List[A], firstMiss: List[A]): List[A] = { |
|||
val newHead = new ::(origStart.head, Nil) |
|||
var toProcess = origStart.tail |
|||
var currentLast = newHead |
|||
|
|||
// we know that all elements are :: until at least firstMiss.tail |
|||
while (!(toProcess eq firstMiss)) { |
|||
val newElem = new ::(toProcess.head, Nil) |
|||
currentLast.next = newElem |
|||
currentLast = newElem |
|||
toProcess = toProcess.tail |
|||
} |
|||
|
|||
// at this point newHead points to a list which is a duplicate of all the 'in' elements up to the first miss. |
|||
// currentLast is the last element in that list. |
|||
|
|||
// now we are going to try and share as much of the tail as we can, only moving elements across when we have to. |
|||
var next = firstMiss.tail |
|||
var nextToCopy = next // the next element we would need to copy to our list if we cant share. |
|||
while (!next.isEmpty) { |
|||
// generally recommended is next.isNonEmpty but this incurs an extra method call. |
|||
val head: A = next.head |
|||
if (p(head) != isFlipped) { |
|||
next = next.tail |
|||
} else { |
|||
// its not a match - do we have outstanding elements? |
|||
while (!(nextToCopy eq next)) { |
|||
val newElem = new ::(nextToCopy.head, Nil) |
|||
currentLast.next = newElem |
|||
currentLast = newElem |
|||
nextToCopy = nextToCopy.tail |
|||
} |
|||
nextToCopy = next.tail |
|||
next = next.tail |
|||
} |
|||
} |
|||
|
|||
// we have remaining elements - they are unchanged attach them to the end |
|||
if (!nextToCopy.isEmpty) |
|||
currentLast.next = nextToCopy |
|||
|
|||
newHead |
|||
} |
|||
|
|||
val result = noneIn(this) |
|||
releaseFence() |
|||
result |
|||
} |
|||
|
|||
override def partition(p: A => Boolean): (List[A], List[A]) = { |
|||
if (isEmpty) List.TupleOfNil |
|||
else super.partition(p) match { |
|||
case (Nil, xs) => (Nil, this) |
|||
case (xs, Nil) => (this, Nil) |
|||
case pair => pair |
|||
} |
|||
} |
|||
|
|||
final override def toList: List[A] = this |
|||
|
|||
// Override for performance |
|||
override def equals(o: scala.Any): Boolean = { |
|||
@tailrec def listEq(a: List[_], b: List[_]): Boolean = |
|||
(a eq b) || { |
|||
val aEmpty = a.isEmpty |
|||
val bEmpty = b.isEmpty |
|||
if (!(aEmpty || bEmpty) && a.head == b.head) { |
|||
listEq(a.tail, b.tail) |
|||
} |
|||
else { |
|||
aEmpty && bEmpty |
|||
} |
|||
} |
|||
|
|||
o match { |
|||
case that: List[_] => listEq(this, that) |
|||
case _ => super.equals(o) |
|||
} |
|||
} |
|||
|
|||
} |
|||
|
|||
// Internal code that mutates `next` _must_ call `Statics.releaseFence()` if either immediately, or |
|||
// before a newly-allocated, thread-local :: instance is aliased (e.g. in ListBuffer.toList) |
|||
final case class :: [+A](override val head: A, private[scala] var next: List[A @uncheckedVariance]) // sound because `next` is used only locally |
|||
extends List[A] { |
|||
releaseFence() |
|||
override def headOption: Some[A] = Some(head) |
|||
override def tail: List[A] = next |
|||
} |
|||
|
|||
case object Nil extends List[Nothing] { |
|||
override def head: Nothing = throw new NoSuchElementException("head of empty list") |
|||
override def headOption: None.type = None |
|||
override def tail: Nothing = throw new UnsupportedOperationException("tail of empty list") |
|||
override def last: Nothing = throw new NoSuchElementException("last of empty list") |
|||
override def init: Nothing = throw new UnsupportedOperationException("init of empty list") |
|||
override def knownSize: Int = 0 |
|||
override def iterator: Iterator[Nothing] = Iterator.empty |
|||
override def unzip[A1, A2](implicit asPair: Nothing => (A1, A2)): (List[A1], List[A2]) = EmptyUnzip |
|||
|
|||
@transient |
|||
private[this] val EmptyUnzip = (Nil, Nil) |
|||
} |
|||
|
|||
/** |
|||
* $factoryInfo |
|||
* @define coll list |
|||
* @define Coll `List` |
|||
*/ |
|||
@SerialVersionUID(3L) |
|||
object List extends StrictOptimizedSeqFactory[List] { |
|||
private val TupleOfNil = (Nil, Nil) |
|||
|
|||
def from[B](coll: collection.IterableOnce[B]): List[B] = Nil.prependedAll(coll) |
|||
|
|||
def newBuilder[A]: Builder[A, List[A]] = new ListBuffer() |
|||
|
|||
def empty[A]: List[A] = Nil |
|||
|
|||
@transient |
|||
private[collection] val partialNotApplied = new Function1[Any, Any] { def apply(x: Any): Any = this } |
|||
} |
@ -0,0 +1,7 @@ |
|||
{ |
|||
// Use IntelliSense to learn about possible attributes. |
|||
// Hover to view descriptions of existing attributes. |
|||
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 |
|||
"version": "0.2.0", |
|||
"configurations": [] |
|||
} |
@ -0,0 +1,5 @@ |
|||
{ |
|||
"files.watcherExclude": { |
|||
"**/target": true |
|||
} |
|||
} |
@ -0,0 +1,77 @@ |
|||
|
|||
// The simplest possible sbt build file is just one line: |
|||
|
|||
scalaVersion := "2.13.3" |
|||
// That is, to create a valid sbt build, all you've got to do is define the |
|||
// version of Scala you'd like your project to use. |
|||
|
|||
// ============================================================================ |
|||
|
|||
// Lines like the above defining `scalaVersion` are called "settings". Settings |
|||
// are key/value pairs. In the case of `scalaVersion`, the key is "scalaVersion" |
|||
// and the value is "2.13.3" |
|||
|
|||
// It's possible to define many kinds of settings, such as: |
|||
|
|||
name := "AdOfCo-05" |
|||
organization := "is.rud.scala" |
|||
version := "1.0" |
|||
|
|||
// Note, it's not required for you to define these three settings. These are |
|||
// mostly only necessary if you intend to publish your library's binaries on a |
|||
// place like Sonatype or Bintray. |
|||
|
|||
|
|||
// Want to use a published library in your project? |
|||
// You can define other libraries as dependencies in your build like this: |
|||
|
|||
libraryDependencies += "org.scala-lang.modules" %% "scala-parser-combinators" % "1.1.2" |
|||
|
|||
// Here, `libraryDependencies` is a set of dependencies, and by using `+=`, |
|||
// we're adding the scala-parser-combinators dependency to the set of dependencies |
|||
// that sbt will go and fetch when it starts up. |
|||
// Now, in any Scala file, you can import classes, objects, etc., from |
|||
// scala-parser-combinators with a regular import. |
|||
|
|||
// TIP: To find the "dependency" that you need to add to the |
|||
// `libraryDependencies` set, which in the above example looks like this: |
|||
|
|||
// "org.scala-lang.modules" %% "scala-parser-combinators" % "1.1.2" |
|||
|
|||
// You can use Scaladex, an index of all known published Scala libraries. There, |
|||
// after you find the library you want, you can just copy/paste the dependency |
|||
// information that you need into your build file. For example, on the |
|||
// scala/scala-parser-combinators Scaladex page, |
|||
// https://index.scala-lang.org/scala/scala-parser-combinators, you can copy/paste |
|||
// the sbt dependency from the sbt box on the right-hand side of the screen. |
|||
|
|||
// IMPORTANT NOTE: while build files look _kind of_ like regular Scala, it's |
|||
// important to note that syntax in *.sbt files doesn't always behave like |
|||
// regular Scala. For example, notice in this build file that it's not required |
|||
// to put our settings into an enclosing object or class. Always remember that |
|||
// sbt is a bit different, semantically, than vanilla Scala. |
|||
|
|||
// ============================================================================ |
|||
|
|||
// Most moderately interesting Scala projects don't make use of the very simple |
|||
// build file style (called "bare style") used in this build.sbt file. Most |
|||
// intermediate Scala projects make use of so-called "multi-project" builds. A |
|||
// multi-project build makes it possible to have different folders which sbt can |
|||
// be configured differently for. That is, you may wish to have different |
|||
// dependencies or different testing frameworks defined for different parts of |
|||
// your codebase. Multi-project builds make this possible. |
|||
|
|||
// Here's a quick glimpse of what a multi-project build looks like for this |
|||
// build, with only one "subproject" defined, called `root`: |
|||
|
|||
// lazy val root = (project in file(".")). |
|||
// settings( |
|||
// inThisBuild(List( |
|||
// organization := "ch.epfl.scala", |
|||
// scalaVersion := "2.13.3" |
|||
// )), |
|||
// name := "hello-world" |
|||
// ) |
|||
|
|||
// To learn more about multi-project builds, head over to the official sbt |
|||
// documentation at http://www.scala-sbt.org/documentation.html |
@ -0,0 +1,42 @@ |
|||
// See R or Python code for today's challenge description |
|||
|
|||
object Main extends App { |
|||
|
|||
def partition(seq: String, lb: Int, ub: Int, trigger: Character): Int = { |
|||
|
|||
var lbm = lb |
|||
var ubm = ub |
|||
|
|||
for (part <- seq) { |
|||
val amt = ((ubm - lbm)/2).floor.toInt + 1 |
|||
if (part == trigger) { |
|||
ubm = ubm - amt |
|||
} else { |
|||
lbm = lbm + amt |
|||
} |
|||
} |
|||
|
|||
return(if (seq.takeRight(1) == trigger) ubm else lbm) |
|||
|
|||
} |
|||
|
|||
val bufferedSource = io.Source.fromFile("/Users/hrbrmstr/Development/2020-code-advent/input/05-01.txt") |
|||
val input = (for (line <- bufferedSource.getLines()) yield line).toList |
|||
bufferedSource.close |
|||
|
|||
val records = input.map( (line : String) => |
|||
(partition(line.substring(0, 7), 0, 127, 'F') * 8) + partition(line.substring(7, 10), 0, 7, 'L') |
|||
).sortWith(_ < _) |
|||
|
|||
|
|||
// 05-01 |
|||
|
|||
println(records.max) |
|||
|
|||
// 04-02 |
|||
|
|||
val diff = records.sliding(2).map { case Seq(x, y, _*) => y - x }.toList |
|||
|
|||
println(records(diff.indexWhere(_ > 1)) + 1) |
|||
|
|||
} |
Loading…
Reference in new issue