diff options
Diffstat (limited to 'src/library/scalax/collection/generic/IterableView.scala')
-rwxr-xr-x | src/library/scalax/collection/generic/IterableView.scala | 121 |
1 files changed, 121 insertions, 0 deletions
diff --git a/src/library/scalax/collection/generic/IterableView.scala b/src/library/scalax/collection/generic/IterableView.scala new file mode 100755 index 0000000000..b9b826b0a4 --- /dev/null +++ b/src/library/scalax/collection/generic/IterableView.scala @@ -0,0 +1,121 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2003-2008, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +// $Id: Iterable.scala 15188 2008-05-24 15:01:02Z stepancheg $ + +package scalax.collection.generic + +/** A non-strict projection of an iterable. + * @author Sean McDirmid + * @author Martin Odersky + * @note this should really be a virtual class of SequenceFactory + */ +trait IterableView[+UC[/*+*/B] <: Iterable[B], /*+*/A] extends Iterable[A] { self => + + val origin: Iterable[_] + def elements: Iterator[A] + + val underlying: Iterable[_] = origin match { + case v: IterableView[t, _] => v.underlying + case _ => origin + } + + private def isDelay = elements eq underlying.elements + + private[this] var forced: UC[A] = _ + private[this] var wasForced = false + + def force: UC[A] = { + if (!wasForced) { + forced = { + val b = underlying.newBuilder[A] + for (x <- elements) + b += x + b.result + }.asInstanceOf[UC[A]] + wasForced = true + } + forced + } + + def newBuilder[A] = underlying.newBuilder[A] + + /** Builds a new view object. This method needs to be overridden in subclasses + * which refine in IterableView type + */ + protected def newView[B](elems: Iterator[B]) = new IterableView[UC, B] { + val origin = if (self.isDelay) self.origin else self + val elements = elems + } + + /** Non-strict variant of @see IterableLike.++ */ + override def ++[B >: A](that: Iterator[B]): IterableView[UC, B] = newView(elements ++ that) + + /** Non-strict variant of @see IterableLike.++ */ + override def ++[B >: A](that: Iterable[B]): IterableView[UC, B] = newView(elements ++ that.elements) + + /** Non-strict variant of @see IterableLike.map */ + override def map[B](f: A => B): IterableView[UC, B] = newView(elements map f) + + /** Non-strict variant of @see IterableLike.flatMap */ + override def flatMap[B](f: A => Iterable[B]): IterableView[UC, B] = newView(elements flatMap (f(_).elements)) + + /** Non-strict variant of @see IterableLike.filter */ + override def filter(p: A => Boolean): IterableView[UC, A] = newView(elements filter p) + + /** Non-strict variant of @see IterableLike.partition */ + override def partition(p: A => Boolean): (IterableView[UC, A], IterableView[UC, A]) = { + val (li, ri) = elements partition p + (newView(li), newView(ri)) + } + + /** Non-strict variant of @see IterableLike.zip */ + override def zip[B](other: Iterable[B]): IterableView[UC, (A, B)] = newView(elements zip other.elements) + + /** Non-strict variant of @see IterableLike.zipWithIndex */ + override def zipWithIndex: IterableView[UC, (A, Int)] = newView(elements.zipWithIndex) + + /* Non-strict variant of @see IterableLike.zipAll + * This is not enabled because it can't be specialized in VectorView: + * VectorView is not covariant, yet must maintain updatability. Impossible to do this + * with this type signature. + override def zipAll[B, A1 >: A, B1 >: B](that: Iterable[B], thisElem: A1, thatElem: B1): IterableView[UC, (A1, B1)] = + newView(elements zipAll (that.elements, thisElem, thatElem)) + */ + + /** Non-strict variant of @see Iterable.take */ + override def take(n: Int): IterableView[UC, A] = newView(elements take n) + + /** Non-strict variant of @see Iterable.drop */ + override def drop(n: Int): IterableView[UC, A] = newView(elements drop n) + + /** Non-strict variant of @see Iterable.splitAt */ + override def splitAt(n: Int): (IterableView[UC, A], IterableView[UC, A]) = (take(n), drop(n)) + + /** Non-strict variant of @see Iterable.slice */ + override def slice(from: Int, until: Int): IterableView[UC, A] = newView(elements slice (from, until)) + + /** Non-strict variant of @see Iterable.takeWhile */ + override def takeWhile(p: A => Boolean): IterableView[UC, A] = newView(elements takeWhile p) + + /** Non-strict variant of @see Iterable.dropWhile */ + override def dropWhile(p: A => Boolean): IterableView[UC, A] = newView(elements dropWhile p) + + /** Non-strict variant of @see Iterable.span */ + override def span(p: A => Boolean): (IterableView[UC, A], IterableView[UC, A]) = (takeWhile(p), dropWhile(p)) + + /** The projection resulting from the concatenation of this projection with the <code>rest</code> projection. + * @param rest The projection that gets appended to this projection + * @deprecated Use ++ instead + */ + @deprecated def append[B >: A](rest : => Iterable[B]): IterableView[UC, B] = this ++ rest.elements + + override def stringPrefix = origin.stringPrefix+"V" + + +} |