ses
ses

Reputation: 13342

scala iterator and stream example. stream fails on reuse

I have a code (sentences is iterator here):

  def count() = {
    var count = 0
    for(sentence <- sentences.toStream) count += sentence.words.size
    count
  }

and test:

// first
val wordCount1 = wordCounter.count()
wordCount1 must_== 10

// second time - should be same result
val wordCount2 = wordCounter.count()
wordCount2 must_== 10   // fails: result is 0

Last test fails:

'0' is not equal to '10'
Expected :10
Actual   :0

But since I use sentences.toStream in the code above, I suppose to have stream at it is (I can reuse it, theoretically).

Q: why does it fail?


EDIT: I was hoping that toStream would help. Like was described here: (..."You can traverse the same Stream multiple times"...). It's like I never touch iterator, I have deal with stream.

But I got.. sentences.toStream used UP sentence-iterator so I can not use it anymore. I just expected when doing toStream on iterator is do a logic like getting stream-'link' to iterator without touching iterator itself. Ok..

Upvotes: 0

Views: 2354

Answers (2)

ses
ses

Reputation: 13342

Actually toStream helps. I just changed the code to expect stream but not iterator, in order not trying create stream from 'dead' iterator on second+ traverse.

Then my solution is:

val stream = new SentenceFileReader("two_lines_file.txt").toStream

val wordCounter = new WordCounter(stream) // now it accepts stream but not iterator

// first
val wordCount1 = wordCounter.count()
wordCount1 must_== 10

// second time - same result
val wordCount2 = wordCounter.count()
wordCount2 must_== 10

Upvotes: 3

Brian
Brian

Reputation: 20285

It fails because the sentences Iterator has been expended. One is not suppose to call an Iterator after a method on it has been called except for the next and hasNext methods.

A simple example shows this:

scala> val it = Iterator(1,2,3)
it: Iterator[Int] = non-empty iterator

scala> it.foreach(println(_))
1
2
3

scala> it.foreach(println(_))

scala> 

In your case sentences has been expended on the first call and is empty on the second one giving a size of 0.

Calling toStream on it does not change this. You get back an empty Stream. If you want to reuse sentences assign it to a list with val l = sentences.toList before calling count.

Upvotes: 4

Related Questions