-
Notifications
You must be signed in to change notification settings - Fork 21
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#iterator should be override. #3273
Comments
Imported From: https://issues.scala-lang.org/browse/SI-3273?orig=1 |
Eastsun (eastsun) said: val fib: Stream[Int] = 1 #:: 1 #:: (fib, fib.tail).zippedx.map(_ + _) While I expected to get fib(3) without any exception. I must have something missed. Is there any one to tell me why. I believe it is the key to fix #3273 import scala.collection.{TraversableLike, IterableLike}
import scala.collection.generic.CanBuildFrom
class LazyItrSt[A](stream: Stream[A]) {
class LazyCell[T](st: => Stream[T]){ lazy val v = st }
def iterator: Iterator[A] = new Iterator[A] {
var these = new LazyCell(stream)
def hasNext: Boolean = !these.v.isEmpty
def next: A =
if (hasNext) {
val result = these.v.head;
these =new LazyCell(these.v.tail);
result
} else Iterator.empty.next
override def toList: List[A] = stream.toList
}
}
class Zippedx[+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 = (new LazyItrSt(coll2.asInstanceOf[Stream[El2]])).iterator
for(el1 <- coll1 if elems2.hasNext) yield f(el1, elems2.next)
}
}
class Zippedx2[+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)
}
}
object Debug extends Application {
implicit def t2t[T1,T2](t: (T1,T2)) = new {
def zippedx[Repr1, El1, Repr2, El2](implicit w1: T1 => TraversableLike[El1, Repr1],
w2: T2 => IterableLike[El2, Repr2]): Zippedx[Repr1, El1, Repr2, El2]
= new Zippedx[Repr1, El1, Repr2, El2](t._1, t._2)
}
implicit def t2t2[T1,T2](t: (T1,T2)) = new {
def zippedx2[Repr1, El1, Repr2, El2](implicit w1: T1 => TraversableLike[El1, Repr1],
w2: T2 => IterableLike[El2, Repr2]): Zippedx2[Repr1, El1, Repr2, El2]
= new Zippedx2[Repr1, El1, Repr2, El2](t._1, t._2)
}
val fib: Stream[Int] = 1 #:: 1 #:: (fib, fib.tail).zippedx2.map(_ + _)
//val fib: Stream[Int] = 1 #:: 1 #:: (fib, fib.tail).zippedx.map(_ + _)
println(fib(2))
println(fib(3))
}
|
Eastsun (eastsun) said: |
Eastsun (eastsun) said: class Stream[A] {
...
class LazyCell[T](st: => Stream[T]){ lazy val v = st }
def iterator: Iterator[A] = new Iterator[A] {
var these = new LazyCell(Stream.this)
def hasNext: Boolean = !these.v.isEmpty
def next: A =
if (hasNext) {
val result = these.v.head
val tmp = these //Here...
these =new LazyCell(tmp.v.tail);
result
} else Iterator.empty.next
override def toList: List[A] = Stream.this.toList
}
} |
@paulp said:
I applaud your progress, but so far in my limited fiddling with your implementation I haven't gotten zipped to behave fully lazily. I can't spend any more time on it, but it would be great if you could take this all the way to a patch against trunk. (I can't guarantee it'll go into 2.8 though.) |
Eastsun (eastsun) said:
It works fine in my tests. Anyway, this ticket(SI-3273) should be fixed override /*LinearSeqLike*/
def iterator: Iterator[A] = new Iterator[A] {
class LazyCell(st: => Stream[A]){ lazy val v = st }
var these = new LazyCell(self)
def hasNext: Boolean = !these.v.isEmpty
def next: A =
if (hasNext) {
val cur = these.v
val result = cur.head
these = new LazyCell(cur.tail)
result
} else Iterator.empty.next
override def toStream: Stream[A] = these.v
override def toList: List[A] = these.v.toList
} |
@dubochet said: |
@SethTisue said: is there something short I can type into the REPL to see for myself that Stream.iterator needs to be "more lazy"? |
Eastsun (eastsun) said:
scala> val num1: Stream[Int] = 1 #:: num1.map{ _+1 }
num1: Stream[Int] = Stream(1, ?)
scala> num1.take(10).toList
res1: List[Int] = List(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
scala> val num2: Stream[Int] = 1 #:: num2.iterator.map{ _+1 }.toStream
num2: Stream[Int] = Stream(1, ?)
scala> num2.take(10).toList
java.lang.StackOverflowError
at scala.collection.LinearSeqLike$$$$anon$$1.hasNext(LinearSeqLike.scala:54)
at scala.collection.Iterator$$$$anon$$19.hasNext(Iterator.scala:368)
at scala.collection.Iterator$$class.toStream(Iterator.scala:1011)
at scala.collection.Iterator$$$$anon$$19.toStream(Iterator.scala:367)
at $$anonfun$$1.apply(<console>:5)
at $$anonfun$$1.apply(<console>:5)
at scala.collection.immutable.Stream$$Cons.tail(Stream.scala:571)
at scala.collection.immutable.Stream$$Cons.tail(Stream.scala:565)
at scala.collection.LinearSeqLike$$$$anon$$1.next(LinearSeqLike.scala:57)
at scala.collection.Iterator$$$$anon$$19.next(Iterator.scala:369)
at scala.collection.Iterator$$class.toStream(Iterator.scala:1011)
at scala.collection.Iterator$$$$anon$$19.toStream(Iterator.scala:367)
at $$anonfun$$1.apply(<... And with lazy iterator: scala> def lazyItr[A](xs: Stream[A]): Iterator[A] = new Iterator[A] {
|
| class LazyCell(st: => Stream[A]){ lazy val v = st }
|
| var these = new LazyCell(xs)
| def hasNext: Boolean = !these.v.isEmpty
| def next: A =
| if (hasNext) {
| val cur = these.v
| val result = cur.head
| these = new LazyCell(cur.tail)
| result
| } else Iterator.empty.next
| }
lazyItr: [A](xs: Stream[A])Iterator[A]
scala> val num3: Stream[Int] = 1 #:: lazyItr(num3).map{ _+1 }.toStream
num1: Stream[Int] = Stream(1, ?)
scala> num3.take(10).toList
res0: List[Int] = List(1, 2, 3, 4, 5, 6, 7, 8, 9, 10) |
Eastsun (eastsun) said: |
@paulp said:
In case you're not on the list, see my comments at http://permalink.gmane.org/gmane.comp.lang.scala.internals/3890 . (Further discussion at #3526 please.) |
/*My English is not so good, forgive my expression */
The iterator method of Stream is defined in LinearSeqLike now. I think it should be override in class Stream to make it more lazy.
In my opinion, it should be something like following:
The text was updated successfully, but these errors were encountered: