Scala итератор и поток. поток не используется при повторном использовании
У меня есть код (sentences
is iterator
здесь):
def count() = {
var count = 0
for(sentence <- sentences.toStream) count += sentence.words.size
count
}
и тест:
// 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
Последний тест не выполнен:
'0' is not equal to '10'
Expected :10
Actual :0
Но так как я использую sentences.toStream
в приведенном выше коде, я полагаю, что в нем есть stream
(я могу его повторно использовать, теоретически).
Q: почему это не удается?
EDIT:
Я надеялся, что toStream
поможет. Как описано здесь: (... "Вы можете пройти один и тот же stream
несколько раз"...). Как будто я никогда не касаюсь итератора, у меня есть дело с потоком.
Но я получил.. sentences.toStream
использовал UP sentence-iterator
, поэтому я больше не могу его использовать. Я просто ожидал, когда toStream
на iterator
выполняет логику, как получение stream-'link 'для итератора, не касаясь самого итератора. Ok..
Ответы
Ответ 1
Он терпит неудачу, потому что был израсходован sentences
Iterator
. Один из них не должен вызывать Iterator
после того, как метод на нем был вызван, за исключением методов next
и hasNext
.
Простой пример показывает это:
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>
В вашем случае sentences
был израсходован на первый вызов и пуст на втором, указав размер 0.
Вызов toStream
на нем не изменит этого. Вы возвращаетесь пустым Stream
. Если вы хотите повторно использовать sentences
назначить его списку с val l = sentences.toList
перед вызовом счетчика.
Ответ 2
Фактически toStream
помогает. Я просто изменил код, чтобы ожидать stream
, но не iterator
, чтобы не пытаться создать поток из "мертвого" итератора на втором + траверсе.
Тогда мое решение:
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