Permalink
Browse files

SI-6415, overly eager evaluation in Stream.

The lengthCompare method in LinearSeqOptimized was looking one
step further than it needed to in order to give the correct
result, which was creating some unwanted side effects related to
Streams.
  • Loading branch information...
1 parent 1284c3c commit 24a033b2aa4174fe8e9c3c02372b6508ef404601 @jedesah jedesah committed with paulp Nov 22, 2012
@@ -247,14 +247,20 @@ trait LinearSeqOptimized[+A, +Repr <: LinearSeqOptimized[A, Repr]] extends Linea
}
override /*SeqLike*/
- def lengthCompare(len: Int): Int = {
- var i = 0
- var these = self
- while (!these.isEmpty && i <= len) {
- i += 1
- these = these.tail
+ def lengthCompare(len: Int): Int = {
+ // TODO: Remove this method when incrementing a major revision
+ // This method is the same as in SeqLike, no need to redefine it
+ if (len < 0) 1
+ else {
+ var i = 0
+ val it = iterator
+ while (it.hasNext) {
+ if (i == len) return if (it.hasNext) 1 else 0
+ it.next()
+ i += 1
+ }
+ i - len
}
- i - len
}
override /*SeqLike*/
@@ -84,13 +84,17 @@ trait SeqLike[+A, +Repr] extends Any with IterableLike[A, Repr] with GenSeqLike[
* if computing `length` is cheap.
*/
def lengthCompare(len: Int): Int = {
- var i = 0
- val it = iterator
- while (it.hasNext && i <= len) {
- it.next()
- i += 1
+ if (len < 0) 1
+ else {
+ var i = 0
+ val it = iterator
+ while (it.hasNext) {
+ if (i == len) return if (it.hasNext) 1 else 0
+ it.next()
+ i += 1
+ }
+ i - len
}
- i - len
}
override /*IterableLike*/ def isEmpty: Boolean = lengthCompare(0) == 0
@@ -1,5 +1,8 @@
Stream()
Stream()
+true
+true
+true
Array(1)
Stream(1, ?)
@@ -8,12 +11,21 @@ Stream()
Stream()
Stream(1)
Stream()
+true
+true
+true
+true
Array(1, 2)
Stream(2)
Stream()
Stream(1, 2)
Stream()
+true
+true
+true
+true
+true
999
512
@@ -23,3 +35,5 @@ Stream(100001, ?)
true
true
705082704
+
+true
@@ -2,6 +2,9 @@ object Test extends App {
val s0: Stream[Int] = Stream.empty
println(s0.take(1))
println(s0.takeWhile(_ > 0))
+ println(s0.lengthCompare(-5) > 0)
+ println(s0.lengthCompare(0) == 0)
+ println(s0.lengthCompare(5) < 0)
println
val s1 = Stream.cons(1, Stream.empty)
@@ -12,6 +15,10 @@ object Test extends App {
println(s1.drop(2))
println(s1.drop(-1))
println(s1.dropWhile(_ > 0))
+ println(s1.lengthCompare(-5) > 0)
+ println(s1.lengthCompare(0) > 0)
+ println(s1.lengthCompare(1) == 0)
+ println(s1.lengthCompare(5) < 0)
println
val s2 = s1.append(Stream.cons(2, Stream.empty))
@@ -20,6 +27,11 @@ object Test extends App {
println(s2.drop(2))
println(s2.drop(-1))
println(s2.dropWhile(_ > 0))
+ println(s2.lengthCompare(-5) > 0)
+ println(s2.lengthCompare(0) > 0)
+ println(s2.lengthCompare(1) > 0)
+ println(s2.lengthCompare(2) == 0)
+ println(s2.lengthCompare(5) < 0)
println
val s3 = Stream.range(1, 1000) //100000 (ticket #153: Stackoverflow)
@@ -43,4 +55,12 @@ object Test extends App {
println(Stream.from(1).take(size).foldLeft(0)(_ + _))
val arr = new Array[Int](size)
Stream.from(1).take(size).copyToArray(arr, 0)
+
+ println
+
+ // ticket #6415
+ lazy val x = { println("evaluated"); 1 }
+ val s4 = 0 #:: x #:: Stream.empty
+
+ println(s4.isDefinedAt(0))
}

0 comments on commit 24a033b

Please sign in to comment.