From 0be42af7a28a92739712636289009f3996370388 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Tue, 14 Jul 2009 15:35:07 +0000 Subject: made streams and views more lazy by always skip... made streams and views more lazy by always skipping builder --- .../collection/generic/SequenceViewTemplate.scala | 14 +++++---- .../generic/TraversableViewTemplate.scala | 27 +++++++++++------ .../scala/collection/immutable/Stream.scala | 35 +++++++++++++++------- 3 files changed, 50 insertions(+), 26 deletions(-) diff --git a/src/library/scala/collection/generic/SequenceViewTemplate.scala b/src/library/scala/collection/generic/SequenceViewTemplate.scala index 4fb918628d..998b61271a 100644 --- a/src/library/scala/collection/generic/SequenceViewTemplate.scala +++ b/src/library/scala/collection/generic/SequenceViewTemplate.scala @@ -151,18 +151,20 @@ trait SequenceViewTemplate[+A, override def reverse: This = newReversed.asInstanceOf[This] override def patch[B >: A, That](from: Int, patch: Sequence[B], replaced: Int)(implicit bf: BuilderFactory[B, That, This]): That = { - val b = bf(thisCollection) - if (b.isInstanceOf[NoBuilder[_]]) newPatched(from, patch, replaced).asInstanceOf[That] - else super.patch[B, That](from, patch, replaced)(bf) + newPatched(from, patch, replaced).asInstanceOf[That] +// was: val b = bf(thisCollection) +// if (b.isInstanceOf[NoBuilder[_]]) newPatched(from, patch, replaced).asInstanceOf[That] +// else super.patch[B, That](from, patch, replaced)(bf) } override def padTo[B >: A, That](len: Int, elem: B)(implicit bf: BuilderFactory[B, That, This]): That = patch(length, fill(len - length)(elem), 0) override def zip[A1 >: A, B, That](that: Sequence[B])(implicit bf: BuilderFactory[(A1, B), That, This]): That = { - val b = bf(thisCollection) - if (b.isInstanceOf[NoBuilder[_]]) newZipped(that).asInstanceOf[That] - else super.zip[A1, B, That](that)(bf) + newZipped(that).asInstanceOf[That] +// was: val b = bf(thisCollection) +// if (b.isInstanceOf[NoBuilder[_]]) newZipped(that).asInstanceOf[That] +// else super.zip[A1, B, That](that)(bf) } override def zipWithIndex[A1 >: A, That](implicit bf: BuilderFactory[(A1, Int), That, This]): That = diff --git a/src/library/scala/collection/generic/TraversableViewTemplate.scala b/src/library/scala/collection/generic/TraversableViewTemplate.scala index 9ea1f6d2fc..84d5b9d0b3 100644 --- a/src/library/scala/collection/generic/TraversableViewTemplate.scala +++ b/src/library/scala/collection/generic/TraversableViewTemplate.scala @@ -19,6 +19,12 @@ import TraversableView.NoBuilder * target="contentFrame">Traversable.
* Every subclass has to implement the foreach method. *

+ * @note Methods such as map/flatMap on this will not invoke the implicitly passed + * Builder factory, but will return a new view directly, to preserve by-name behavior. + * The new view is then cast to the factory's result type. + * This means that every BuilderFactory that takes a + * View as its From type parameter must yield the same view (or a generic superclass of it) + * as its result parameter. If that assumption is broken, cast errors might result. * * @author Martin Odersky * @version 2.8 @@ -136,23 +142,26 @@ self => protected def newTakenWhile(p: A => Boolean): Transformed[A] = new TakenWhile { val pred = p } override def ++[B >: A, That](that: Traversable[B])(implicit bf: BuilderFactory[B, That, This]): That = { - val b = bf(thisCollection) - if (b.isInstanceOf[NoBuilder[_]]) newAppended(that).asInstanceOf[That] - else super.++[B, That](that)(bf) + newAppended(that).asInstanceOf[That] +// was: val b = bf(thisCollection) +// if (b.isInstanceOf[NoBuilder[_]]) newAppended(that).asInstanceOf[That] +// else super.++[B, That](that)(bf) } override def ++[B >: A, That](that: Iterator[B])(implicit bf: BuilderFactory[B, That, This]): That = ++[B, That](that.toStream) override def map[B, That](f: A => B)(implicit bf: BuilderFactory[B, That, This]): That = { - val b = bf(thisCollection) - if (b.isInstanceOf[NoBuilder[_]]) newMapped(f).asInstanceOf[That] - else super.map[B, That](f)(bf) + newMapped(f).asInstanceOf[That] +// was: val b = bf(thisCollection) +// if (b.isInstanceOf[NoBuilder[_]]) newMapped(f).asInstanceOf[That] +// else super.map[B, That](f)(bf) } override def flatMap[B, That](f: A => Traversable[B])(implicit bf: BuilderFactory[B, That, This]): That = { - val b = bf(thisCollection) - if (b.isInstanceOf[NoBuilder[_]]) newFlatMapped(f).asInstanceOf[That] - else super.flatMap[B, That](f)(bf) + newFlatMapped(f).asInstanceOf[That] +// was: val b = bf(thisCollection) +// if (b.isInstanceOf[NoBuilder[_]]) newFlatMapped(f).asInstanceOf[That] +// else super.flatMap[B, That](f)(bf) } override def filter(p: A => Boolean): This = newFiltered(p).asInstanceOf[This] diff --git a/src/library/scala/collection/immutable/Stream.scala b/src/library/scala/collection/immutable/Stream.scala index 523fda9465..9f609796f5 100644 --- a/src/library/scala/collection/immutable/Stream.scala +++ b/src/library/scala/collection/immutable/Stream.scala @@ -117,8 +117,9 @@ self => override def ++[B >: A, That](that: Traversable[B])(implicit bf: BuilderFactory[B, That, Stream[A]]): That = { def loop(these: Stream[A]): Stream[B] = if (these.isEmpty) that.toStream else new Stream.Cons(these.head, loop(these.tail)) - if (bf.isInstanceOf[Stream.StreamBuilderFactory[_]]) loop(this).asInstanceOf[That] - else super.++(that) + loop(this).asInstanceOf[That] +// was: if (bf.isInstanceOf[Stream.StreamBuilderFactory[_]]) loop(this).asInstanceOf[That] +// else super.++(that) } /** Create a new stream which contains all elements of this stream @@ -137,8 +138,9 @@ self => override def map[B, That](f: A => B)(implicit bf: BuilderFactory[B, That, Stream[A]]): That = { def loop(these: Stream[A]): Stream[B] = if (these.isEmpty) Stream.Empty else new Stream.Cons(f(these.head), loop(these.tail)) - if (bf.isInstanceOf[Stream.StreamBuilderFactory[_]]) loop(this).asInstanceOf[That] - else super.map(f) + loop(this).asInstanceOf[That] +// was: if (bf.isInstanceOf[Stream.StreamBuilderFactory[_]]) loop(this).asInstanceOf[That] +// else super.map(f) } /** Applies the given function f to each element of @@ -154,10 +156,11 @@ self => else { val seg = f(these.head) if (seg.isEmpty) loop(these.tail) - else seg.toStream ++ loop(these.tail) + else seg.toStream append loop(these.tail) } - if (bf.isInstanceOf[Stream.StreamBuilderFactory[_]]) loop(this).asInstanceOf[That] - else super.flatMap(f) + loop(this).asInstanceOf[That] +// was: if (bf.isInstanceOf[Stream.StreamBuilderFactory[_]]) loop(this).asInstanceOf[That] +// else super.flatMap(f) } /** Returns all the elements of this stream that satisfy the @@ -200,8 +203,9 @@ self => def loop(these: Stream[A], elems2: Iterator[B]): Stream[(A1, B)] = if (these.isEmpty || !elems2.hasNext) Stream.Empty else new Stream.Cons((these.head, elems2.next), loop(these.tail, elems2)) - if (bf.isInstanceOf[Stream.StreamBuilderFactory[_]]) loop(this, that.iterator).asInstanceOf[That] - else super.zip[A1, B, That](that) + loop(this, that.iterator).asInstanceOf[That] +// was: if (bf.isInstanceOf[Stream.StreamBuilderFactory[_]]) loop(this, that.iterator).asInstanceOf[That] +// else super.zip[A1, B, That](that) } /** Zips this iterable with its indices. `s.zipWithIndex` is equivalent to @@ -315,8 +319,9 @@ self => def loop(len: Int, these: Stream[A]): Stream[B] = if (these.isEmpty) Stream.fill(len)(elem) else new Stream.Cons(these.head, loop(len - 1, these.tail)) - if (bf.isInstanceOf[Stream.StreamBuilderFactory[_]]) loop(len, this).asInstanceOf[That] - else super.padTo(len, elem) + loop(len, this).asInstanceOf[That] +// was: if (bf.isInstanceOf[Stream.StreamBuilderFactory[_]]) loop(len, this).asInstanceOf[That] +// else super.padTo(len, elem) } /** A list consisting of all elements of this list in reverse order. @@ -347,6 +352,14 @@ self => */ object Stream extends SequenceFactory[Stream] { + /** The factory for streams. + * @note Methods such as map/flatMap will not invoke the Builder factory, + * but will return a new stream directly, to preserve laziness. + * The new stream is then cast to the factory's result type. + * This means that every BuilderFactory that takes a + * Stream as its From type parameter must yield a stream as its result parameter. + * If that assumption is broken, cast errors might result. + */ class StreamBuilderFactory[A] extends VirtualBuilderFactory[A] implicit def builderFactory[A]: BuilderFactory[A, Stream[A], Coll] = new StreamBuilderFactory[A] -- cgit v1.2.3