You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
627 lines
24 KiB
627 lines
24 KiB
/*
|
|
* 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()
|
|
}
|
|
|