diff options
author | Paul Phillips <paulp@improving.org> | 2011-03-11 12:13:58 +0000 |
---|---|---|
committer | Paul Phillips <paulp@improving.org> | 2011-03-11 12:13:58 +0000 |
commit | be49752855a1a6997d4112eeff351e1c119a8a93 (patch) | |
tree | ee2cef3642b675420d47ff30bda9ddb2b74f1c30 /src/library/scala/collection/immutable/Stream.scala | |
parent | 67c461b2d9c19d51e40e1f3ff23455cead1413b5 (diff) | |
download | scala-be49752855a1a6997d4112eeff351e1c119a8a93.tar.gz scala-be49752855a1a6997d4112eeff351e1c119a8a93.tar.bz2 scala-be49752855a1a6997d4112eeff351e1c119a8a93.zip |
A patch for views. Most relevant change:
Almost all view classes now list parents like
trait Appended[B >: A] extends super.Appended[B] with Transformed[B]
instead of the former
trait Appended[B >: A] extends Transformed[B] with super.Appended[B]
because as it was, the implementation of foreach in
TraversableViewLike#Transformed was repeatedly trumping overrides found
in e.g. IterableLike. This change was not without its own consequences,
and much of the rest of the patch is dealing with that. A more general
issue is clearly revealed here: there is no straightforward way to deal
with trait composition and overrides when some methods should prefer B
over A and some the reverse. (It's more like A through Z in this case.)
That closes #4279, with some views being five orders of magnitude slower
than necessary. There is a test that confirms they'll stay performance
neighbors.
In the view classes (Zipped, Mapped, etc.) I attended to them with
comb and brush until they were reasonably consistent. I only use
"override" where necessary and throw in some "final" in the interests
of trying to anchor the composition outcome. I also switched the
newSliced, newZipped, etc. methods to use early init syntax since a
number have abstract vals and I found at least one bug originating with
uninitialized access.
There was a piece of a parallel collections scalacheck test failing,
which
I disabled out of expedience - am emailing prokopec.
There is plenty of work left to do but paulp must get back to other 2.9
issues. This is the Zurich->SF airplane patch. No review.
Diffstat (limited to 'src/library/scala/collection/immutable/Stream.scala')
-rw-r--r-- | src/library/scala/collection/immutable/Stream.scala | 81 |
1 files changed, 38 insertions, 43 deletions
diff --git a/src/library/scala/collection/immutable/Stream.scala b/src/library/scala/collection/immutable/Stream.scala index b12b312d21..2a4c29c05e 100644 --- a/src/library/scala/collection/immutable/Stream.scala +++ b/src/library/scala/collection/immutable/Stream.scala @@ -269,33 +269,8 @@ self => new StreamWithFilter(x => p(x) && q(x)) } - /** See #3273 and test case run/bug3273 for motivation. */ - final class StreamIterator extends Iterator[A] { - // A call-by-need cell. - class LazyCell(st: => Stream[A]) { - lazy val v = st - } - - private var these = new LazyCell(self) - def hasNext: Boolean = these.v.nonEmpty - def next: A = - if (isEmpty) Iterator.empty.next - else { - val cur = these.v - val result = cur.head - these = new LazyCell(cur.tail) - result - } - override def toStream = { - val result = these.v - these = new LazyCell(Stream.empty) - result - } - override def toList = toStream.toList - } - /** A lazier Iterator than LinearSeqLike's. */ - override def iterator: Iterator[A] = new StreamIterator + override def iterator: Iterator[A] = new StreamIterator(self) /** Apply the given function <code>f</code> to each element of this linear sequence * (while respecting the order of the elements). @@ -392,21 +367,12 @@ self => b } + override def mkString(sep: String): String = mkString("", sep, "") + override def mkString: String = mkString("") override def mkString(start: String, sep: String, end: String): String = { this.force super.mkString(start, sep, end) } - - override def mkString(sep: String): String = { - this.force - super.mkString(sep) - } - - override def mkString: String = { - this.force - super.mkString - } - override def toString = super.mkString(stringPrefix + "(", ", ", ")") override def splitAt(n: Int): (Stream[A], Stream[A]) = (take(n), drop(n)) @@ -422,6 +388,10 @@ self => else if (n == 1) cons(head, Stream.empty) else cons(head, tail take n-1) + @tailrec final override def drop(n: Int): Stream[A] = + if (n <= 0 || isEmpty) this + else tail drop n-1 + /** A substream starting at index `from` and extending up to (but not including) * index `until`. * @@ -534,6 +504,31 @@ self => } +/** See #3273 and test case run/bug3273 for motivation. */ +final class StreamIterator[+A](self: Stream[A]) extends Iterator[A] { + // A call-by-need cell. + class LazyCell(st: => Stream[A]) { + lazy val v = st + } + + private var these = new LazyCell(self) + def hasNext: Boolean = these.v.nonEmpty + def next: A = + if (isEmpty) Iterator.empty.next + else { + val cur = these.v + val result = cur.head + these = new LazyCell(cur.tail) + result + } + override def toStream = { + val result = these.v + these = new LazyCell(Stream.empty) + result + } + override def toList = toStream.toList +} + /** * The object <code>Stream</code> provides helper functions * to manipulate streams. @@ -644,7 +639,7 @@ object Stream extends SeqFactory[Stream] { * @param f the function that's repeatedly applied * @return the stream returning the infinite sequence of values `start, f(start), f(f(start)), ...` */ - def iterate[A](start: A)(f: A => A): Stream[A] = new Cons(start, iterate(f(start))(f)) + def iterate[A](start: A)(f: A => A): Stream[A] = cons(start, iterate(f(start))(f)) override def iterate[A](start: A, len: Int)(f: A => A): Stream[A] = iterate(start)(f) take len @@ -658,7 +653,7 @@ object Stream extends SeqFactory[Stream] { * @return the stream starting at value <code>start</code>. */ def from(start: Int, step: Int): Stream[Int] = - new Cons(start, from(start+step, step)) + cons(start, from(start+step, step)) /** * Create an infinite stream starting at <code>start</code> @@ -676,14 +671,14 @@ object Stream extends SeqFactory[Stream] { * @param elem the element composing the resulting stream * @return the stream containing an infinite number of elem */ - def continually[A](elem: => A): Stream[A] = new Cons(elem, continually(elem)) + def continually[A](elem: => A): Stream[A] = cons(elem, continually(elem)) override def fill[A](n: Int)(elem: => A): Stream[A] = - if (n <= 0) Empty else new Cons(elem, fill(n-1)(elem)) + if (n <= 0) Empty else cons(elem, fill(n-1)(elem)) override def tabulate[A](n: Int)(f: Int => A): Stream[A] = { def loop(i: Int): Stream[A] = - if (i >= n) Empty else new Cons(f(i), loop(i+1)) + if (i >= n) Empty else cons(f(i), loop(i+1)) loop(0) } @@ -692,7 +687,7 @@ object Stream extends SeqFactory[Stream] { import num._ if (if (step < zero) start <= end else end <= start) Empty - else new Cons(start, range(start + step, end, step)) + else cons(start, range(start + step, end, step)) } private[immutable] def filteredTail[A](stream: Stream[A], p: A => Boolean) = { |