summaryrefslogtreecommitdiff
path: root/src/library
diff options
context:
space:
mode:
authorAleksandar Pokopec <aleksandar.prokopec@epfl.ch>2010-11-19 12:38:14 +0000
committerAleksandar Pokopec <aleksandar.prokopec@epfl.ch>2010-11-19 12:38:14 +0000
commit78ae055e5231d5a9ef3aae6228863cc3ddcf963e (patch)
tree9cd101df8f5c9c89ff123c224599233a9fe2dc57 /src/library
parenta01f074d3e3229db905e21e78469ab02dc6ca0cf (diff)
downloadscala-78ae055e5231d5a9ef3aae6228863cc3ddcf963e.tar.gz
scala-78ae055e5231d5a9ef3aae6228863cc3ddcf963e.tar.bz2
scala-78ae055e5231d5a9ef3aae6228863cc3ddcf963e.zip
Fixes #3686 by special casing Stream transforme...
Fixes #3686 by special casing Stream transformers depending on target type. Review by extempore.
Diffstat (limited to 'src/library')
-rw-r--r--src/library/scala/collection/immutable/Stream.scala55
1 files changed, 39 insertions, 16 deletions
diff --git a/src/library/scala/collection/immutable/Stream.scala b/src/library/scala/collection/immutable/Stream.scala
index 02a17427ef..6a7d0535fc 100644
--- a/src/library/scala/collection/immutable/Stream.scala
+++ b/src/library/scala/collection/immutable/Stream.scala
@@ -120,6 +120,10 @@ self =>
*/
@inline private def asThat[That](x: AnyRef): That = x.asInstanceOf[That]
@inline private def asStream[B](x: AnyRef): Stream[B] = x.asInstanceOf[Stream[B]]
+ @inline private def buildsThis[B, That](bf: CanBuildFrom[Stream[A], B, That]) = bf.isInstanceOf[Stream.StreamCanBuildFrom[_]]
+ @inline private def ifTargetThis[B, That](bf: CanBuildFrom[Stream[A], B, That])(ifIs: => Stream[B])(ifNot: => That): That =
+ if (buildsThis(bf)) ifIs.asInstanceOf[That]
+ else ifNot
// Overridden methods from Traversable
@@ -139,10 +143,12 @@ self =>
*/
override def ++[B >: A, That](that: TraversableOnce[B])(implicit bf: CanBuildFrom[Stream[A], B, That]): That =
// we assume there is no other builder factory on streams and therefore know that That = Stream[A]
- asThat[That](
+ ifTargetThis[B, That](bf) {
if (isEmpty) that.toStream
else new Stream.Cons(head, asStream[A](tail ++ that))
- )
+ } {
+ super.++(that)(bf)
+ }
/**
* Create a new stream which contains all intermediate results of applying the operator
@@ -150,10 +156,12 @@ self =>
* @note This works because the target type of the Builder That is a Stream.
*/
override final def scanLeft[B, That](z: B)(op: (B, A) => B)(implicit bf: CanBuildFrom[Stream[A], B, That]): That =
- asThat[That](
+ ifTargetThis[B, That](bf) {
if (isEmpty) Stream(z)
else new Stream.Cons(z, asStream[B](tail.scanLeft(op(z, head))(op)))
- )
+ } {
+ super.scanLeft(z)(op)(bf)
+ }
/** Returns the stream resulting from applying the given function
* `f` to each element of this stream.
@@ -162,11 +170,14 @@ self =>
* @return <code>f(a<sub>0</sub>), ..., f(a<sub>n</sub>)</code> if this
* sequence is <code>a<sub>0</sub>, ..., a<sub>n</sub></code>.
*/
- override final def map[B, That](f: A => B)(implicit bf: CanBuildFrom[Stream[A], B, That]): That =
- asThat[That](
+ override final def map[B, That](f: A => B)(implicit bf: CanBuildFrom[Stream[A], B, That]): That = {
+ ifTargetThis[B, That](bf) {
if (isEmpty) Stream.Empty
else new Stream.Cons(f(head), asStream[B](tail map f))
- )
+ } {
+ super.map(f)(bf)
+ }
+ }
/** Applies the given function `f` to each element of
* this stream, then concatenates the results.
@@ -180,7 +191,7 @@ self =>
// we assume there is no other builder factory on streams and therefore know that That = Stream[B]
// optimisations are not for speed, but for functionality
// see tickets #153, #498, #2147, and corresponding tests in run/ (as well as run/stream_flatmap_odds.scala)
- asThat[That](
+ ifTargetThis[B, That](bf) {
if (isEmpty) Stream.Empty
else {
// establish !prefix.isEmpty || nonEmptyPrefix.isEmpty
@@ -195,7 +206,9 @@ self =>
if (nonEmptyPrefix.isEmpty) Stream.empty
else prefix append asStream[B](nonEmptyPrefix.tail flatMap f)
}
- )
+ } {
+ super.flatMap(f)(bf)
+ }
/** Returns all the elements of this stream that satisfy the
* predicate <code>p</code>. The order of the elements is preserved.
@@ -221,20 +234,24 @@ self =>
override def map[B, That](f: A => B)(implicit bf: CanBuildFrom[Stream[A], B, That]): That = {
def tailMap = asStream[B](tail withFilter p map f)
- asThat[That](
+ ifTargetThis[B, That](bf) {
if (isEmpty) Stream.Empty
else if (p(head)) new Stream.Cons(f(head), tailMap)
else tailMap
- )
+ } {
+ super.map(f)(bf)
+ }
}
override def flatMap[B, That](f: A => Traversable[B])(implicit bf: CanBuildFrom[Stream[A], B, That]): That = {
def tailFlatMap = asStream[B](tail withFilter p flatMap f)
- asThat[That](
+ ifTargetThis[B, That](bf) {
if (isEmpty) Stream.Empty
else if (p(head)) f(head).toStream append tailFlatMap
else tailFlatMap
- )
+ } {
+ super.flatMap(f)(bf)
+ }
}
override def foreach[B](f: A => B) =
@@ -319,10 +336,12 @@ self =>
*/
override final def zip[A1 >: A, B, That](that: Iterable[B])(implicit bf: CanBuildFrom[Stream[A], (A1, B), That]): That =
// we assume there is no other builder factory on streams and therefore know that That = Stream[(A1, B)]
- asThat[That](
+ ifTargetThis[(A1, B), That](bf) {
if (this.isEmpty || that.isEmpty) Stream.Empty
else new Stream.Cons((this.head, that.head), asStream[(A1, B)](this.tail zip that.tail))
- )
+ } {
+ super.zip(that)(bf)
+ }
/** Zips this iterable with its indices. `s.zipWithIndex` is equivalent to
* `s zip s.indices`
@@ -456,7 +475,11 @@ self =>
if (these.isEmpty) Stream.fill(len)(elem)
else new Stream.Cons(these.head, loop(len - 1, these.tail))
- asThat[That](loop(len, this))
+ ifTargetThis[B, That](bf) {
+ loop(len, this)
+ } {
+ super.padTo(len, elem)(bf)
+ }
// was: if (bf.isInstanceOf[Stream.StreamCanBuildFrom[_]]) loop(len, this).asInstanceOf[That]
// else super.padTo(len, elem)
}