scala.collection.generic.GenTraversableFactory.scala Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of scala-library Show documentation
Show all versions of scala-library Show documentation
Standard library for the Scala Programming Language
/* __ *\
** ________ ___ / / ___ Scala API **
** / __/ __// _ | / / / _ | (c) 2006-2013, LAMP/EPFL **
** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ **
** /____/\___/_/ |_/____/_/ | | **
** |/ **
\* */
package scala.collection
package generic
import scala.language.higherKinds
/** A template for companion objects of `Traversable` and subclasses thereof.
* This class provides a set of operations to create `$Coll` objects.
* It is typically inherited by companion objects of subclasses of `Traversable`.
*
* @since 2.8
*
* @define coll collection
* @define Coll `Traversable`
* @define factoryInfo
* This object provides a set of operations to create `$Coll` values.
* @author Martin Odersky
* @version 2.8
* @define canBuildFromInfo
* The standard `CanBuildFrom` instance for $Coll objects.
* @see CanBuildFrom
* @define genericCanBuildFromInfo
* The standard `CanBuildFrom` instance for $Coll objects.
* The created value is an instance of class `GenericCanBuildFrom`,
* which forwards calls to create a new builder to the
* `genericBuilder` method of the requesting collection.
* @see CanBuildFrom
* @see GenericCanBuildFrom
*/
abstract class GenTraversableFactory[CC[X] <: GenTraversable[X] with GenericTraversableTemplate[X, CC]]
extends GenericCompanion[CC] {
// A default implementation of GenericCanBuildFrom which can be cast
// to whatever is desired.
private class ReusableCBF extends GenericCanBuildFrom[Nothing] {
override def apply() = newBuilder[Nothing]
}
// Working around SI-4789 by using a lazy val instead of an object.
lazy val ReusableCBF: GenericCanBuildFrom[Nothing] = new ReusableCBF
/** A generic implementation of the `CanBuildFrom` trait, which forwards
* all calls to `apply(from)` to the `genericBuilder` method of
* $coll `from`, and which forwards all calls of `apply()` to the
* `newBuilder` method of this factory.
*/
class GenericCanBuildFrom[A] extends CanBuildFrom[CC[_], A, CC[A]] {
/** Creates a new builder on request of a collection.
* @param from the collection requesting the builder to be created.
* @return the result of invoking the `genericBuilder` method on `from`.
*/
def apply(from: Coll) = from.genericBuilder[A]
/** Creates a new builder from scratch
* @return the result of invoking the `newBuilder` method of this factory.
*/
def apply() = newBuilder[A]
}
/** Concatenates all argument collections into a single $coll.
*
* @param xss the collections that are to be concatenated.
* @return the concatenation of all the collections.
*/
def concat[A](xss: Traversable[A]*): CC[A] = {
val b = newBuilder[A]
// At present we're using IndexedSeq as a proxy for "has a cheap size method".
if (xss forall (_.isInstanceOf[IndexedSeq[_]]))
b.sizeHint(xss.map(_.size).sum)
for (xs <- xss.seq) b ++= xs
b.result
}
/** Produces a $coll containing the results of some element computation a number of times.
* @param n the number of elements contained in the $coll.
* @param elem the element computation
* @return A $coll that contains the results of `n` evaluations of `elem`.
*/
def fill[A](n: Int)(elem: => A): CC[A] = {
val b = newBuilder[A]
b.sizeHint(n)
var i = 0
while (i < n) {
b += elem
i += 1
}
b.result
}
/** Produces a two-dimensional $coll containing 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
* @return A $coll that contains the results of `n1 x n2` evaluations of `elem`.
*/
def fill[A](n1: Int, n2: Int)(elem: => A): CC[CC[A]] =
tabulate(n1)(_ => fill(n2)(elem))
/** Produces a three-dimensional $coll containing 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
* @return A $coll that contains the results of `n1 x n2 x n3` evaluations of `elem`.
*/
def fill[A](n1: Int, n2: Int, n3: Int)(elem: => A): CC[CC[CC[A]]] =
tabulate(n1)(_ => fill(n2, n3)(elem))
/** Produces a four-dimensional $coll containing 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
* @return A $coll that contains the results of `n1 x n2 x n3 x n4` evaluations of `elem`.
*/
def fill[A](n1: Int, n2: Int, n3: Int, n4: Int)(elem: => A): CC[CC[CC[CC[A]]]] =
tabulate(n1)(_ => fill(n2, n3, n4)(elem))
/** Produces a five-dimensional $coll containing 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
* @return A $coll that contains the results of `n1 x n2 x n3 x n4 x n5` evaluations of `elem`.
*/
def fill[A](n1: Int, n2: Int, n3: Int, n4: Int, n5: Int)(elem: => A): CC[CC[CC[CC[CC[A]]]]] =
tabulate(n1)(_ => fill(n2, n3, n4, n5)(elem))
/** Produces a $coll containing values of a given function over a range of integer values starting from 0.
* @param n The number of elements in the $coll
* @param f The function computing element values
* @return A $coll consisting of elements `f(0), ..., f(n -1)`
*/
def tabulate[A](n: Int)(f: Int => A): CC[A] = {
val b = newBuilder[A]
b.sizeHint(n)
var i = 0
while (i < n) {
b += f(i)
i += 1
}
b.result
}
/** Produces a two-dimensional $coll 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
* @return A $coll consisting of elements `f(i1, i2)`
* for `0 <= i1 < n1` and `0 <= i2 < n2`.
*/
def tabulate[A](n1: Int, n2: Int)(f: (Int, Int) => A): CC[CC[A]] =
tabulate(n1)(i1 => tabulate(n2)(f(i1, _)))
/** Produces a three-dimensional $coll 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 3nd dimension
* @param f The function computing element values
* @return A $coll consisting of elements `f(i1, i2, i3)`
* for `0 <= i1 < n1`, `0 <= i2 < n2`, and `0 <= i3 < n3`.
*/
def tabulate[A](n1: Int, n2: Int, n3: Int)(f: (Int, Int, Int) => A): CC[CC[CC[A]]] =
tabulate(n1)(i1 => tabulate(n2, n3)(f(i1, _, _)))
/** Produces a four-dimensional $coll 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 3nd dimension
* @param n4 the number of elements in the 4th dimension
* @param f The function computing element values
* @return A $coll consisting of elements `f(i1, i2, i3, i4)`
* for `0 <= i1 < n1`, `0 <= i2 < n2`, `0 <= i3 < n3`, and `0 <= i4 < n4`.
*/
def tabulate[A](n1: Int, n2: Int, n3: Int, n4: Int)(f: (Int, Int, Int, Int) => A): CC[CC[CC[CC[A]]]] =
tabulate(n1)(i1 => tabulate(n2, n3, n4)(f(i1, _, _, _)))
/** Produces a five-dimensional $coll 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 3nd 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
* @return A $coll consisting of elements `f(i1, i2, i3, i4, i5)`
* for `0 <= i1 < n1`, `0 <= i2 < n2`, `0 <= i3 < n3`, `0 <= i4 < n4`, and `0 <= i5 < n5`.
*/
def tabulate[A](n1: Int, n2: Int, n3: Int, n4: Int, n5: Int)(f: (Int, Int, Int, Int, Int) => A): CC[CC[CC[CC[CC[A]]]]] =
tabulate(n1)(i1 => tabulate(n2, n3, n4, n5)(f(i1, _, _, _, _)))
/** Produces a $coll containing a sequence of increasing of integers.
*
* @param start the first element of the $coll
* @param end the end value of the $coll (the first value NOT contained)
* @return a $coll with values `start, start + 1, ..., end - 1`
*/
def range[T: Integral](start: T, end: T): CC[T] = range(start, end, implicitly[Integral[T]].one)
/** Produces a $coll containing equally spaced values in some integer interval.
* @param start the start value of the $coll
* @param end the end value of the $coll (the first value NOT contained)
* @param step the difference between successive elements of the $coll (must be positive or negative)
* @return a $coll with values `start, start + step, ...` up to, but excluding `end`
*/
def range[T: Integral](start: T, end: T, step: T): CC[T] = {
val num = implicitly[Integral[T]]
import num._
if (step == zero) throw new IllegalArgumentException("zero step")
val b = newBuilder[T]
b sizeHint immutable.NumericRange.count(start, end, step, false)
var i = start
while (if (step < zero) end < i else i < end) {
b += i
i += step
}
b.result
}
/** Produces a $coll containing repeated applications of a function to a start value.
*
* @param start the start value of the $coll
* @param len the number of elements contained inthe $coll
* @param f the function that's repeatedly applied
* @return a $coll with `len` values in the sequence `start, f(start), f(f(start)), ...`
*/
def iterate[A](start: A, len: Int)(f: A => A): CC[A] = {
val b = newBuilder[A]
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
}
}