I just wanted to explore the behaviors of the iterators of a String object and a List[Int] object in REPL and the tests are as shown below:
scala> val list = List(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16)
list: List[Int] = List(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16)
scala> val itL = list.iterator
itL: Iterator[Int] = non-empty iterator
scala> List(8,5,list.size-13).map(itL.take(_).mkString)
res85: List[String] = List(12345678, 910111213, 141516)
scala> val st = "abcdefghijklmnop"
st: String = abcdefghijklmnop
scala> val itS = st.iterator
itS: Iterator[Char] = non-empty iterator
scala> List(8,5,st.size-13).map(itS.take(_).mkString)
res84: List[String] = List(abcdefgh, abcde, abc)
Why the iterators are behaving differently? My expected output in String object's case is:
List[String] = List(abcdefgh, ijklm, nop)
Can somebody explain this if possible with examples.
Another Observation is: The behaviour of the iterator of the Range object is also exactly similar to String object
as seen below:
scala> val x = (1 to 16)
x: scala.collection.immutable.Range.Inclusive = Range 1 to 16
scala> val t = (1 to 16).iterator
t: Iterator[Int] = non-empty iterator
scala> List(8,5,x.size-13).map(t.take(_).mkString)
res103: List[String] = List(12345678, 12345, 123)
If the Range is converted to List or Set the respective iterators are behaving exactly as per my expectation always:
scala> val x1 = (1 to 16).toList
x1: List[Int] = List(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16)
scala> val t1 = x1.iterator
t1: Iterator[Int] = non-empty iterator
scala> List(8,5,x1.size-13).map(t1.take(_).mkString)
res104: List[String] = List(12345678, 910111213, 141516)
scala> val x2 = (1 to 16).toSet
x2: scala.collection.immutable.Set[Int] = Set(5, 10, 14, 1, 6, 9, 13, 2, 12, 7, 3, 16, 11, 8, 4, 15)
scala> val t2 = x2.iterator
t2: Iterator[Int] = non-empty iterator
scala> List(8,5,x2.size-13).map(t2.take(_).mkString)
res105: List[String] = List(51014169132, 12731611, 8415)
There's a note attached to the Iterator.take(n:Int) API documentation:
Reuse: After calling this method, one should discard the iterator it was called on, and use only the iterator that was returned. Using the old iterator is undefined, subject to change, and may result in changes to the new iterator as well.
It looks like you've discovered some "undefined" behavior.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With