我只是尝试新的kotlin
语言。我遇到了生成无限列表的序列。我生成了一个序列并尝试打印前10个元素。但是下面的代码没有打印任何内容:
fun main(args: Array<String>) {
val generatePrimeFrom2 = generateSequence(3){ it + 2 }
print(generatePrimeFrom2.toList().take(10))
}
但是当我在take(10).toList()
语句中更改print
时,它运行正常。为什么会这样?
这段代码对我来说很好:
fun main(args: Array<String>) {
val generatePrimeFrom2 = generateSequence(3){ it + 2 }
print(generatePrimeFrom2.take(10).toList())
}
答案 0 :(得分:8)
generateSequence
函数生成一个无限的序列,或者当传递给它的lambda返回null
时完成。在您的情况下,它是{ it + 2 }
,它永远不会返回null
,所以序列是无限的。
当你在序列上调用.toList()
时,它将尝试收集所有序列元素,因此如果序列是无限的,则永远不会停止(除非索引溢出或发生内存不足错误),所以它没有打印任何东西,因为它没有完成。
在第二种情况下,相反,在尝试收集其项目之前,您使用.take(10)
限制序列中的元素数量。然后.toList()
电话会收集10个项目并完成。
如果您查看此问答语关于Sequence<T>
和Iterable<T>
之间的差异,可能会更加清晰:(link)
答案 1 :(得分:5)
这是提示 - &gt; generate infinite list
。在第一个解决方案中,您首先要创建一个列表(等待无穷大)然后获取前10个元素。
在第二个片段中,从无限列表中,您只获取前10个元素并将其更改为列表
答案 2 :(得分:1)
generatePrimeFrom2.toList()
尝试计算/创建无限长列表
generatePrimeFrom2.toList().take(10)
然后从无限长列表中获取前10个元素
它不会打印,因为它正在计算无限长度列表。
然而,generatePrimeFrom2.take(10)
仅尝试计算前10个元素。
generatePrimeFrom2.take(10).toList()
将前10个元素转换为列表。
您知道,generateSequence(3){ it + 2 }
没有结束。所以它有无限的长度
Sequence
没有实际值,在需要时计算,但List
必须有实际值。
答案 3 :(得分:1)
我遇到了生成无限列表的序列。
这实际上并不正确。重点是序列不是列表。它是一个延迟评估的构造,只有您请求的项目才会实际变为“物化”,即它们在堆上分配的内存。
这就是为什么写
不可互换的原因infiniteSeq.toList().take(10)
和
infiniteSeq.take(10).toList()
前者将尝试实例化无限多个项目 - 并且可以预见,会失败。