Careeroza
Creating Sequences
Builders
Example
Infinite sequences are fine as long as you limit them with take or first.
fun fibonacci() = sequence {
var a = 0L
var b = 1L
while (true) {
yield(a)
val next = a + b
a = b
b = next
}
}
fun main() {
println(sequenceOf("a", "b", "c").toList())
println(generateSequence(1) { it * 2 }.take(10).toList())
println(fibonacci().take(12).toList())
// generateSequence stops when the function returns null
val countdown = generateSequence(5) { if (it > 1) it - 1 else null }
println(countdown.toList())
// yieldAll and yield mixed
val pages = sequence {
yield("cover")
yieldAll((1..3).map { "page $it" })
yield("back")
}
println(pages.joinToString(" | "))
}Output
[a, b, c] [1, 2, 4, 8, 16, 32, 64, 128, 256, 512] [0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89] [5, 4, 3, 2, 1] cover | page 1 | page 2 | page 3 | back
Stateful Operations
sorted(), sortedBy and distinct on a sequence must look at all elements before emitting the first one, so they lose most of the laziness benefit. windowed, chunked and zipWithNext stay lazy.
Example
fun main() {
val readings = generateSequence(20) { it + listOf(1, -2, 3, 0, 2)[it % 5] }
println(readings.take(8).toList())
println(readings.take(8).zipWithNext { a, b -> b - a }.toList())
println(readings.take(8).windowed(3) { it.average() }.map { "%.1f".format(it) }.toList())
println(readings.take(8).chunked(3).toList())
}Output
[20, 21, 19, 21, 19, 21, 19, 21] [1, -2, 2, -2, 2, -2, 2] [20.0, 20.3, 19.7, 20.3, 19.7, 20.3] [[20, 21, 19], [21, 19, 21], [19, 21]]