Reputation: 51
I have question regarding the use of Scala's dropWhile predicate with an iterator. Here I have a simple iterator creation:
scala> val it = Iterator("a" , "number" , "of" , "words")
it: Iterator[String] = non-empty iterator
Next I use a dropWhile predicate on it:
scala> it dropWhile ( _.length < 2 )
res52: Iterator[String] = non-empty iterator
Next I perform a next command on the Iterator:
scala> it next
res53: String = of
Now notice the iterator next command returns "of" , one past what it should be.
If I put this same code in a main function, the next will return "a". This is rather confusing. Can someone explain this?
Upvotes: 0
Views: 310
Reputation: 41987
Scala docs explains Iterators
as
An iterator is not a collection, but rather a way to access the elements of a collection one by one. The two basic operations on an iterator it are next and hasNext. A call to it.next() will return the next element of the iterator and advance the state of the iterator. Calling next again on the same iterator will then yield the element one beyond the one returned previously. If there are no more elements to return, a call to next will throw a NoSuchElementException.
And when you applied it dropWhile ( _.length < 2 )
in REPL, its assigned to res52
scala> it dropWhile ( _.length < 2 ) res52: Iterator[String] = non-empty iterator
"a" , "number"
are already accessed. So applying it next
gave you of
which is 100 % correct
In main()
, you must have done
val it = Iterator("a" , "number" , "of" , "words")
it dropWhile ( _.length < 2 )
print(it next)
You can clearly see that it dropWhile ( _.length < 2 )
is not assigned as in REPL. Thus, "a" , "number"
are not yet accessed
So it next
printed a
in main()
I hope the explanation is helpful
Upvotes: 0
Reputation: 144206
From the docs:
It is of particular importance to note that, unless stated otherwise, one should never use an iterator after calling a method on it. The two most important exceptions are also the sole abstract methods: next and hasNext.
You need to assign the result of dropWhile
to a new variable and continue using that e.g.
val remaining = it dropWhile ( _.length < 2 )
remaining.next
Upvotes: 4