I'm migrating some code from Scala to Kotlin, I observe different behaviour:
Scala:
var i = 0
Iterator.continually{
println(s"i=$i")
i += 1
i
}.takeWhile {
_ < 3
}.foreach { i =>
println(s"I=$i")
}
Output:
i=0
I=1
i=1
I=2
i=2
Kotlin equivalent:
fun <A> continousIterator(func: () -> A): Iterable<A> =
object: Iterable<A> {
override fun iterator() =
object: Iterator<A> {
override fun hasNext(): Boolean = true
override fun next(): A = func()
}
}
var i = 0;
fun main() {
continousIterator{
println("i=$i")
i += 1
i
}.takeWhile{
it < 3
}.forEach {
println("I=$it")
}
}
Output:
i=0
i=1
i=2
I=1
I=2
When we have state, the result isn't the same, the calling order of func() and the iterator are different.
I wonder why.
In Kotlin, when takeWhile is called, takeWhile iterates through the sequence immediately and prints 0 to 2, and produces a List. Only after that does the forEach get run, printing 1 and 2.
To replicate the Scala behaviour, you need forEach to consume the sequence, instead of takeWhile. A Sequence can do this:
generateSequence {
println("i=$i")
i += 1
i
}.takeWhile{it < 3}.forEach { println("I=$it")}
Operations on a Sequence are all lazy. They don't consume the sequence unless absolutely necessary.
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