Estou migrando alguns códigos de Scala para Kotlin, observo um comportamento diferente:
Escala:
var i = 0
Iterator.continually{
println(s"i=$i")
i += 1
i
}.takeWhile {
_ < 3
}.foreach { i =>
println(s"I=$i")
}
Saída:
i=0
I=1
i=1
I=2
i=2
Equivalente em Kotlin:
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")
}
}
Saída:
i=0
i=1
i=2
I=1
I=2
Quando temos estado, o resultado não é o mesmo, a ordem de chamada de func()
e iterator
são diferentes.
Eu quero saber porque.
No Kotlin, quando
takeWhile
é chamado,takeWhile
itera imediatamente pela sequência, imprime de 0 a 2 e produz um arquivoList
. Só depois disso oforEach
get é executado, imprimindo 1 e 2.Para replicar o comportamento do Scala, você precisa
forEach
consumir a sequência, em vez detakeWhile
. ASequence
pode fazer isso:As operações em a
Sequence
são todas preguiçosas. Eles não consomem a sequência, a menos que seja absolutamente necessário.