Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Stream#withFilter should be override. #3265

Closed
scabug opened this issue Apr 7, 2010 · 10 comments
Closed

Stream#withFilter should be override. #3265

scabug opened this issue Apr 7, 2010 · 10 comments
Assignees

Comments

@scabug
Copy link

scabug commented Apr 7, 2010

Now the method withFilter of scala.collection.immutable.Stream is defined in scala.collection.TraversableLike. This lead to some problems:

scala> val nums = Stream.from(1)
nums: scala.collection.immutable.Stream[Int] = Stream(1, ?)

scala> val even = for(n <- nums if n%2 == 0) yield n
java.lang.OutOfMemoryError: Java heap space
        at scala.collection.TraversableOnce$$class.toList(TraversableOnce.scala:393)
        at scala.collection.mutable.WrappedArray.toList(WrappedArray.scala:25)
        at scala.collection.immutable.List$$.apply(List.scala:448)
        at scala.collection.mutable.LazyBuilder.$$plus$$eq(LazyBuilder.scala:24)
        at scala.collection.mutable.LazyBuilder.$$plus$$eq(LazyBuilder.scala:21)
        at scala.collection.TraversableLike$$WithFilter$$$$anonfun$$map$$2.apply(TraversableLike.scala:775)
        at scala.collection.immutable.Stream.foreach(Stream.scala:195)
        at scala.collection.TraversableLike$$WithFilter.map(TraversableLike.scala:774)
        at .<init>(<console>:6)
        at .<clinit>(<console>)
        at RequestResult$$.<init>(<console>:9)
        at RequestResult$$.<clinit>(<console>)
        at RequestResult$$scala_repl_resul...
scala>

I think we should override withFilter in Stream like following(not test):

abstract class Stream[+A] extends LinearSeq[A] 
                             with GenericTraversableTemplate[A, Stream]
                             with LinearSeqOptimized[A, Stream[A]] {
self =>
  ...
  
  final override def withFilter(p: A => Boolean): WithFilter = new StreamFilter(p)
  
  class StreamFilter(p: A => Boolean) extends WithFilter(p) {
  
    def map[B, That](f: A => B)(implicit bf: CanBuildFrom[Repr, B, That]): That = 
      (if(isEmpty) Stream.Empty
	   else if(p(head)) new Stream.Cons(f(head), tail.withFilter(p).map(f).asInstanceOf[Stream[B]])
       else tail.withFilter(p).map(f).asInstanceOf[Stream[B]]
	  ).asInstanceOf[That]
	
    def flatMap[B, That](f: A => Traversable[B])(implicit bf: CanBuildFrom[Repr, B, That]): That = 
	  (if(isEmpty) Stream.Empty
       else if(p(head)) f(head).toStream append tail.withFilter(p).flatMap(f).asInstanceOf[Stream[B]]
	   else tail.withFilter(p).flatMap(f).asInstanceOf[Stream[B]]
	  ).asInstanceOf[That]
 
    def foreach[U](f: A => U): Unit = 
      for (x <- self) 
        if (p(x)) f(x)

    def withFilter(q: A => Boolean): WithFilter = 
      new StreamFilter(x => p(x) && q(x))
  }
}
@scabug
Copy link
Author

scabug commented Apr 7, 2010

Imported From: https://issues.scala-lang.org/browse/SI-3265?orig=1
Reporter: Eastsun (eastsun)

@scabug
Copy link
Author

scabug commented Apr 7, 2010

@dubochet said:
Paul, would you like to comment on this proposal?

@scabug
Copy link
Author

scabug commented Apr 7, 2010

Eastsun (eastsun) said:
BTW, I think we could fix Ticket #2634 in a very simple way after this ticket be fixed.

@scabug
Copy link
Author

scabug commented Apr 7, 2010

@paulp said:
Replying to [comment:2 dubochet]:

Paul, would you like to comment on this proposal?

Sure! He's right in principle, and I don't know if I'm going to run into some nutty issue in practice. Shoot, I already added a whole withFilter implementation to poor little Option. It doesn't look like any collection with nontrivial differences can avoid it without suffering consequences. Anyway, I'll take that as a hint that I should check that patch out and commit something if I can.

@scabug
Copy link
Author

scabug commented Apr 7, 2010

@paulp said:
(In r21375) Gave Stream a lazy withFilter implementation. Now you too
can have a collection containing all the even numbers in the
universe and still be home in time for tea. Threw in some
Stream cleanups for free. Closes #3265, review by community.

@scabug
Copy link
Author

scabug commented Apr 7, 2010

@paulp said:
Replying to [comment:3 Eastsun]:

BTW, I think we could fix Ticket #2634 in a very simple way after this ticket be fixed.

You are now equipped to demonstrate! Because I tried, and it doesn't look like a simple task to me.

@scabug
Copy link
Author

scabug commented Apr 7, 2010

Eastsun (eastsun) said:
Replying to [comment:6 extempore]:

Replying to [comment:3 Eastsun]:

BTW, I think we could fix Ticket #2634 in a very simple way after this ticket be fixed.

You are now equipped to demonstrate! Because I tried, and it doesn't look like a simple task to me.

Take Tuple2 for example, I think #2634 would be fixed if we chang the implementation of class Tuple2#Zipped like this:

class Zipped[+Repr1, +El1, +Repr2, +El2](coll1: TraversableLike[El1, Repr1], coll2: IterableLike[El2, Repr2]) { 
    def map[B, To](f: (El1, El2) => B)(implicit cbf: CanBuildFrom[Repr1, B, To]): To = {
      val elems2 = coll2.iterator

      for(el1 <- coll1 if(elems2.hasNext)) yield f(el1, elems2.next)
    }
	...
}

And Tuple2#zip should be changed in the same way.

Since I don't have chance to test it, I apologize if I have missed something.

@scabug
Copy link
Author

scabug commented Apr 8, 2010

@paulp said:
Replying to [comment:7 Eastsun]:

Since I don't have chance to test it, I apologize if I have missed something.

I encourage you to try it out. I'm hopeful that it's me who is missing something, because I'd like it to work. I agree that the for comprehensions should be rewritten like that now that withFilter exists, but it doesn't make any difference when it comes to termination.

@scabug
Copy link
Author

scabug commented Apr 9, 2010

Eastsun (eastsun) said:
Replying to [comment:8 extempore]:

Replying to [comment:7 Eastsun]:

Since I don't have chance to test it, I apologize if I have missed something.

I encourage you to try it out. I'm hopeful that it's me who is missing something, because I'd like it to work. I agree that the for comprehensions should be rewritten like that now that withFilter exists, but it doesn't make any difference when it comes to termination.

It confused me very much. I try to find the reason why it doesn't work as my expected. I find another Ticket #3273.

@scabug
Copy link
Author

scabug commented Apr 9, 2010

Eastsun (eastsun) said:
Replying to [comment:8 extempore]:

I encourage you to try it out. I'm hopeful that it's me who is missing something, because I'd like it to work. I agree that the for comprehensions should be rewritten like that now that withFilter exists, but it doesn't make any difference when it comes to termination.

I have some ideas about #2634 and I post it here: [http://old.nabble.com/Some-ideas-of-lazy-version-takeWhile-method-in-TraversableLike.-td28189940.html]

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants