Scala和Kotlin中的迭代

4
我正在将一些代码从Scala迁移到Kotlin,我观察到了不同的行为:
Scala:
var i = 0

Iterator.continually{
  println(s"i=$i")
  i += 1
  i
}.takeWhile { 
  _ < 3
}.foreach { i =>
  println(s"I=$i")
}

输出:

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() {
    continousIterator{
        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的调用顺序是不同的。
我想知道为什么。

2
它可能是急切地评估takeWhile而不是懒惰地评估。 - undefined
1个回答

4
在Kotlin中,当调用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")}

对于一个序列,所有的操作都是惰性的。除非绝对必要,否则它们不会消耗序列。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接