Scala - iterators and takeWhile

I run the following code snippet:

val it = List(1,1,1,2,2,3,3).iterator.buffered val compare = it.head it.takeWhile(_ == compare).toList 

and it returns (1,1,1). However, if I ran this as:

 val it = List(1,1,1,2,2,3,3).iterator.buffered it.takeWhile(_ == it.head).toList 

I get (1,1). Why is this so? Is head evaluated when takeWhile called, and should the result be the same?

+6
source share
2 answers

Since the iterator is modified, the value of it.head depends on when it was evaluated.

Checking the implementation of takeWhile shows that it removes the iterator head before applying the predicate.

So, in the third iteration, it.head evaluated from the predicate will be 2 , because the third element has already been deleted.

This is an illustration of why you should prefer immutability. It excludes a whole class of non-obvious behavior like this.

+15
source

Adding to @Ben James will answer above. The following is the code for the takeWhile (credits: ben) method:

 def hasNext = hdDefined || tail.hasNext && { hd = tail.next() //line 2 if (p(hd)) hdDefined = true else tail = Iterator.empty hdDefined } 

In the third iteration after line 2, the value is: hd=1 , and the remaining Iterator is List(2,2,3,3) . when p(hd) called, it checks the head iterator, which in this case is 2 . Therefore, it breaks.

0
source

Source: https://habr.com/ru/post/944195/


All Articles