我正在将一些代码从 Scala 迁移到 Kotlin,我观察到不同的行为:
斯卡拉:
var i = 0
Iterator.continually{
println(s"i=$i")
i += 1
i
}.takeWhile { _ < 3}
.foreach { i =>
println(s"I=$i")
}
输出:
Console (F3)
i=0
I=1
i=1
I=2
i=2
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() {
iteradorContinuo{
println("i=$i")
i += 1
i
}.takeWhile{it < 3}.forEach { println("I=$it")}
}
输出:
i=0
i=1
i=2
I=1
I=2
当我们有状态时,结果不一样,
func()
和iterator
的调用顺序不同。
我想知道为什么。
当调用
takeWhile
时,takeWhile
立即迭代序列并打印 0 到 2,并生成 List
。只有在那之后 forEach
才会运行,打印 1 和 2。
要复制 Scala 行为,您需要
forEach
来使用序列,而不是 takeWhile
。 Sequence
可以做到这一点:
generateSequence {
println("i=$i")
i += 1
i
}.takeWhile{it < 3}.forEach { println("I=$it")}
Sequence
上的操作都是惰性的。除非绝对必要,否则它们不会消耗该序列。