scalafunctional-programmingjvmsliding

Strange behavior of Scala


Can any of you explain why this is happening?

val s = "abcdefg"

val slides = s.sliding(4)
val n1 = slides.length
val n2 = slides.dropWhile(foo).length

println(n1) // 4
println(n2) // 0
println(slides.length) // 0

But:

val s = "abcdefg"

println(s.sliding(4).length) // 4
println(s.sliding(4).dropWhile(foo).length) // 3
println(s.sliding(4).length) // 4

Don't pay attention to the function "foo", it's a simple method to check if a string doesn't contain the letter "c".

Unfortunately, I don't understand this programming language behavior. Maybe someone with more knowledge can answer why this is happening.


Solution

  • slides is an Iterator. It is a special kind of "collection", that you can only traverse once.

    Once you ask for its length, it has to scan through (and discard) all of its elements, to count them, so, it becomes empty, and when you ask for its length again (dropWhile is inconsequential here), it is 0.

    This is useful in cases when you need to process a huge collection without loading it into memory all at once (e.g., reading a huge file line by line, to see if it contains the word "google" somewhere).

    sliding returns an iterator, because making it traversable more than once may be expensive, but is rarely needed. If you need to traverse it more than once, do val slides = s.sliding(4).toSeq