summaryrefslogtreecommitdiff
path: root/src/library/scala/collection/TraversableOnce.scala
diff options
context:
space:
mode:
authorAleksandar Pokopec <aleksandar.prokopec@epfl.ch>2011-04-19 16:57:44 +0000
committerAleksandar Pokopec <aleksandar.prokopec@epfl.ch>2011-04-19 16:57:44 +0000
commite6efa7b11f44d2e405d02c563b710023b3ef3e8a (patch)
tree21b815869f52a52f83bf774f770d2244f9eb9e0f /src/library/scala/collection/TraversableOnce.scala
parentbf53d9f48e0e04e6f7fc3b84d3066437c0cc2fc6 (diff)
downloadscala-e6efa7b11f44d2e405d02c563b710023b3ef3e8a.tar.gz
scala-e6efa7b11f44d2e405d02c563b710023b3ef3e8a.tar.bz2
scala-e6efa7b11f44d2e405d02c563b710023b3ef3e8a.zip
Removed GenTravOnceLike and TravOnceLike, put t...
Removed GenTravOnceLike and TravOnceLike, put their functionality to GenTravOnce and TravOnce. Remove immutable Gen* traits. Removing mutable Gen* traits. No review.
Diffstat (limited to 'src/library/scala/collection/TraversableOnce.scala')
-rw-r--r--src/library/scala/collection/TraversableOnce.scala282
1 files changed, 276 insertions, 6 deletions
diff --git a/src/library/scala/collection/TraversableOnce.scala b/src/library/scala/collection/TraversableOnce.scala
index 23e3f2a866..90f1583c58 100644
--- a/src/library/scala/collection/TraversableOnce.scala
+++ b/src/library/scala/collection/TraversableOnce.scala
@@ -13,10 +13,6 @@ import annotation.unchecked.{ uncheckedVariance => uV }
/** A template trait for collections which can be traversed either once only
* or one or more times.
- *
- * All of the methods in this trait are guaranteed to be implemented
- * in a single-threaded manner.
- *
* $traversableonceinfo
*
* @tparam A the element type of the collection
@@ -27,6 +23,24 @@ import annotation.unchecked.{ uncheckedVariance => uV }
* @since 2.8
*
* @define coll traversable or iterator
+ *
+ * @tparam A the element type of the collection
+ *
+ * @define traversableonceinfo
+ * This trait exists primarily to eliminate code duplication between
+ * `Iterator` and `Traversable`, and thus implements some of the common
+ * methods that can be implemented solely in terms of foreach without
+ * access to a `Builder`. It also includes a number of abstract methods
+ * whose implementations are provided by `Iterator`, `Traversable`, etc.
+ * It contains implementations common to `Iterators` and
+ * `Traversables`, such as folds, conversions, and other operations which
+ * traverse some or all of the elements and return a derived value.
+ * Directly subclassing `TraversableOnce` is not recommended - instead,
+ * consider declaring an `Iterator` with a `next` and `hasNext` method,
+ * creating an `Iterator` with one of the methods on the `Iterator` object,
+ * or declaring a subclass of `Traversable`.
+ *
+ * @define coll traversable or iterator
* @define orderDependent
*
* Note: might return different results for different runs, unless the underlying collection type is ordered.
@@ -42,14 +56,270 @@ import annotation.unchecked.{ uncheckedVariance => uV }
*
* Note: will not terminate for infinite-sized collections.
*/
-trait TraversableOnce[+A] extends GenTraversableOnce[A] with TraversableOnceLike[A] {
+trait TraversableOnce[+A] extends GenTraversableOnce[A] {
self =>
- override def seq: TraversableOnce[A] = this
+ /** Self-documenting abstract methods. */
+ def foreach[U](f: A => U): Unit
+ def isEmpty: Boolean
+ def hasDefiniteSize: Boolean
+
+ // Note: We could redefine this in TraversableLike to always return `repr`
+ // of type `Repr`, only if `Repr` had type bounds, which it doesn't, because
+ // not all `Repr` are a subtype `TraversableOnce[A]`.
+ // The alternative is redefining it for maps, sets and seqs. For concrete implementations
+ // we don't have to do this anyway, since they are leaves in the inheritance hierarchy.
+ // Note 2: This is implemented in all collections _not_ inheriting `Traversable[A]`
+ // at least indirectly. Currently, these are `ArrayOps` and `StringOps`.
+ // It is also implemented in `TraversableOnce[A]`.
+ /** A version of this collection with all
+ * of the operations implemented sequentially (i.e. in a single-threaded manner).
+ *
+ * This method returns a reference to this collection. In parallel collections,
+ * it is redefined to return a sequential implementation of this collection. In
+ * both cases, it has O(1) complexity.
+ *
+ * @return a sequential view of the collection.
+ */
+ def seq: TraversableOnce[A]
+
+ /** Presently these are abstract because the Traversable versions use
+ * breakable/break, and I wasn't sure enough of how that's supposed to
+ * function to consolidate them with the Iterator versions.
+ */
+ def forall(p: A => Boolean): Boolean
+ def exists(p: A => Boolean): Boolean
+ def find(p: A => Boolean): Option[A]
+ def copyToArray[B >: A](xs: Array[B], start: Int, len: Int): Unit
+
+ // for internal use
+ protected[this] def reversed = {
+ var elems: List[A] = Nil
+ self.seq foreach (elems ::= _)
+ elems
+ }
+
+ def size: Int = {
+ var result = 0
+ for (x <- self) result += 1
+ result
+ }
+
+ def nonEmpty: Boolean = !isEmpty
+
+ def count(p: A => Boolean): Int = {
+ var cnt = 0
+ for (x <- this)
+ if (p(x)) cnt += 1
+
+ cnt
+ }
+
+ /** Finds the first element of the $coll for which the given partial
+ * function is defined, and applies the partial function to it.
+ *
+ * $mayNotTerminateInf
+ * $orderDependent
+ *
+ * @param pf the partial function
+ * @return an option value containing pf applied to the first
+ * value for which it is defined, or `None` if none exists.
+ * @example `Seq("a", 1, 5L).collectFirst({ case x: Int => x*10 }) = Some(10)`
+ */
+ def collectFirst[B](pf: PartialFunction[A, B]): Option[B] = {
+ for (x <- self.toIterator) { // make sure to use an iterator or `seq`
+ if (pf isDefinedAt x)
+ return Some(pf(x))
+ }
+ None
+ }
+
+ def /:[B](z: B)(op: (B, A) => B): B = foldLeft(z)(op)
+
+ def :\[B](z: B)(op: (A, B) => B): B = foldRight(z)(op)
+
+ def foldLeft[B](z: B)(op: (B, A) => B): B = {
+ var result = z
+ this.seq foreach (x => result = op(result, x))
+ result
+ }
+
+ def foldRight[B](z: B)(op: (A, B) => B): B =
+ reversed.foldLeft(z)((x, y) => op(y, x))
+
+ def reduceLeft[B >: A](op: (B, A) => B): B = {
+ if (isEmpty)
+ throw new UnsupportedOperationException("empty.reduceLeft")
+
+ var first = true
+ var acc: B = 0.asInstanceOf[B]
+
+ for (x <- self) {
+ if (first) {
+ acc = x
+ first = false
+ }
+ else acc = op(acc, x)
+ }
+ acc
+ }
+
+ def reduceRight[B >: A](op: (A, B) => B): B = {
+ if (isEmpty)
+ throw new UnsupportedOperationException("empty.reduceRight")
+
+ reversed.reduceLeft[B]((x, y) => op(y, x))
+ }
+
+ def reduceLeftOption[B >: A](op: (B, A) => B): Option[B] =
+ if (isEmpty) None else Some(reduceLeft(op))
+
+ def reduceRightOption[B >: A](op: (A, B) => B): Option[B] =
+ if (isEmpty) None else Some(reduceRight(op))
+
+ def reduce[A1 >: A](op: (A1, A1) => A1): A1 = reduceLeft(op)
+
+ def reduceOption[A1 >: A](op: (A1, A1) => A1): Option[A1] = reduceLeftOption(op)
+
+ def fold[A1 >: A](z: A1)(op: (A1, A1) => A1): A1 = foldLeft(z)(op)
+
+ def aggregate[B](z: B)(seqop: (B, A) => B, combop: (B, B) => B): B = foldLeft(z)(seqop)
+
+ def sum[B >: A](implicit num: Numeric[B]): B = foldLeft(num.zero)(num.plus)
+ def product[B >: A](implicit num: Numeric[B]): B = foldLeft(num.one)(num.times)
+
+ def min[B >: A](implicit cmp: Ordering[B]): A = {
+ if (isEmpty)
+ throw new UnsupportedOperationException("empty.min")
+
+ reduceLeft((x, y) => if (cmp.lteq(x, y)) x else y)
+ }
+
+ def max[B >: A](implicit cmp: Ordering[B]): A = {
+ if (isEmpty)
+ throw new UnsupportedOperationException("empty.max")
+
+ reduceLeft((x, y) => if (cmp.gteq(x, y)) x else y)
+ }
+
+ def maxBy[B](f: A => B)(implicit cmp: Ordering[B]): A = {
+ if (isEmpty)
+ throw new UnsupportedOperationException("empty.maxBy")
+
+ reduceLeft((x, y) => if (cmp.gteq(f(x), f(y))) x else y)
+ }
+ def minBy[B](f: A => B)(implicit cmp: Ordering[B]): A = {
+ if (isEmpty)
+ throw new UnsupportedOperationException("empty.minBy")
+
+ reduceLeft((x, y) => if (cmp.lteq(f(x), f(y))) x else y)
+ }
+
+ /** Copies all elements of this $coll to a buffer.
+ * $willNotTerminateInf
+ * @param dest The buffer to which elements are copied.
+ */
+ def copyToBuffer[B >: A](dest: Buffer[B]): Unit = dest ++= seq
+
+ def copyToArray[B >: A](xs: Array[B], start: Int): Unit =
+ copyToArray(xs, start, xs.length - start)
+
+ def copyToArray[B >: A](xs: Array[B]): Unit =
+ copyToArray(xs, 0, xs.length)
+
+ def toArray[B >: A : ClassManifest]: Array[B] = {
+ if (isTraversableAgain) {
+ val result = new Array[B](size)
+ copyToArray(result, 0)
+ result
+ }
+ else toBuffer.toArray
+ }
+
+ def toTraversable: Traversable[A]
+
+ def toList: List[A] = new ListBuffer[A] ++= seq toList
+
+ def toIterable: Iterable[A] = toStream
+
+ def toSeq: Seq[A] = toStream
+
+ def toIndexedSeq[B >: A]: immutable.IndexedSeq[B] = immutable.IndexedSeq() ++ seq
+
+ def toBuffer[B >: A]: mutable.Buffer[B] = new ArrayBuffer[B] ++= seq
+
+ def toSet[B >: A]: immutable.Set[B] = immutable.Set() ++ seq
+
+ def toMap[T, U](implicit ev: A <:< (T, U)): immutable.Map[T, U] = {
+ val b = immutable.Map.newBuilder[T, U]
+ for (x <- self)
+ b += x
+
+ b.result
+ }
+
+ def mkString(start: String, sep: String, end: String): String =
+ addString(new StringBuilder(), start, sep, end).toString
+
+ def mkString(sep: String): String = mkString("", sep, "")
+
+ def mkString: String = mkString("")
+
+ /** Appends all elements of this $coll to a string builder using start, end,
+ * and separator strings.
+ * The written text begins with the string `start` and ends with the string
+ * `end`. Inside, the string representations (w.r.t. the method `toString`)
+ * of all elements of this $coll are separated by the string `sep`.
+ *
+ * @param b the string builder to which elements are appended.
+ * @param start the starting string.
+ * @param sep the separator string.
+ * @param end the ending string.
+ * @return the string builder `b` to which elements were appended.
+ */
+ def addString(b: StringBuilder, start: String, sep: String, end: String): StringBuilder = {
+ var first = true
+
+ b append start
+ for (x <- self) {
+ if (first) {
+ b append x
+ first = false
+ }
+ else {
+ b append sep
+ b append x
+ }
+ }
+ b append end
+
+ b
+ }
+
+ /** Appends all elements of this $coll to a string builder using a separator
+ * string. The written text consists of the string representations (w.r.t.
+ * the method `toString`) of all elements of this $coll, separated by the
+ * string `sep`.
+ *
+ * @param b the string builder to which elements are appended.
+ * @param sep the separator string.
+ * @return the string builder `b` to which elements were appended.
+ */
+ def addString(b: StringBuilder, sep: String): StringBuilder = addString(b, "", sep, "")
+
+ /** Appends all elements of this $coll to a string builder.
+ * The written text consists of the string representations (w.r.t. the method
+ * `toString`) of all elements of this $coll without any separator string.
+ *
+ * @param b the string builder to which elements are appended.
+ * @return the string builder `b` to which elements were appended.
+ */
+ def addString(b: StringBuilder): StringBuilder = addString(b, "")
}
+
object TraversableOnce {
implicit def traversableOnceCanBuildFrom[T] = new OnceCanBuildFrom[T]
implicit def wrapTraversableOnce[A](trav: TraversableOnce[A]) = new MonadOps(trav)