George Curington
George Curington

Reputation: 51

Scala dropWhile predicate with iterators

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

Answers (2)

Ramesh Maharjan
Ramesh Maharjan

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.

REPL

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

Main

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

Lee
Lee

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

Related Questions