Sequence Generators with yield
Create lazy sequences with sequence builders, yield, yieldAll, and custom infinite generators.
// Fibonacci sequence
val fibonacci: Sequence<Long> = sequence {
var a = 0L
var b = 1L
while (true) {
yield(a)
val next = a + b
a = b
b = next
}
}
// Collatz sequence
fun collatz(start: Long): Sequence<Long> = sequence {
var n = start
yield(n)
while (n != 1L) {
n = if (n % 2 == 0L) n / 2 else 3 * n + 1
yield(n)
}
}
// Paginated API simulation
data class Page<T>(val items: List<T>, val hasNext: Boolean, val cursor: Int)
fun fetchPage(cursor: Int, pageSize: Int = 5): Page<String> {
val totalItems = 23
val start = cursor
val end = minOf(start + pageSize, totalItems)
val items = (start until end).map { "Item-$it" }
return Page(items, end < totalItems, end)
}
fun allItems(): Sequence<String> = sequence {
var cursor = 0
var hasMore = true
while (hasMore) {
val page = fetchPage(cursor)
yieldAll(page.items)
cursor = page.cursor
hasMore = page.hasNext
}
}
// Tree traversal with sequence
data class TreeNode(val value: String, val children: List<TreeNode> = emptyList())
fun TreeNode.depthFirst(): Sequence<TreeNode> = sequence {
yield(this@depthFirst)
for (child in children) {
yieldAll(child.depthFirst())
}
}
fun TreeNode.breadthFirst(): Sequence<TreeNode> = sequence {
val queue = ArrayDeque<TreeNode>()
queue.add(this@breadthFirst)
while (queue.isNotEmpty()) {
val node = queue.removeFirst()
yield(node)
queue.addAll(node.children)
}
}
// Permutations
fun <T> permutations(list: List<T>): Sequence<List<T>> = sequence {
if (list.size <= 1) {
yield(list)
return@sequence
}
for (i in list.indices) {
val rest = list.toMutableList().apply { removeAt(i) }
for (perm in permutations(rest)) {
yield(listOf(list[i]) + perm)
}
}
}
// Custom range generator
fun dateRange(start: Int, endInclusive: Int, step: Int = 1) = sequence {
var current = start
while (current <= endInclusive) {
yield(current)
current += step
}
}
fun main() {
// Fibonacci
println("Fibonacci (first 10): ${fibonacci.take(10).toList()}")
println("Fib > 100: ${fibonacci.first { it > 100 }}")
// Collatz
val seq = collatz(27)
println("\nCollatz(27): ${seq.take(10).toList()}... (${collatz(27).count()} steps)")
// Paginated API
println("\n--- Paginated ---")
val items = allItems().toList()
println("Total items: ${items.size}")
println("First 5: ${items.take(5)}")
println("Last 5: ${items.takeLast(5)}")
// Lazy processing
println("\n--- Lazy ---")
val result = allItems()
.filter { it.endsWith("0") || it.endsWith("5") }
.take(3)
.toList()
println("Filtered: $result")
// Tree traversal
val tree = TreeNode("root", listOf(
TreeNode("A", listOf(TreeNode("A1"), TreeNode("A2"))),
TreeNode("B", listOf(TreeNode("B1"))),
TreeNode("C")
))
println("\nDFS: ${tree.depthFirst().map { it.value }.toList()}")
println("BFS: ${tree.breadthFirst().map { it.value }.toList()}")
// Permutations (lazy — won't compute all)
val perms = permutations(listOf(1, 2, 3))
println("\nPermutations: ${perms.toList()}")
// Infinite sequence with generateSequence
val powers = generateSequence(1) { it * 2 }
println("\nPowers of 2: ${powers.take(10).toList()}")
// Iterator protocol
println("\nCustom range: ${dateRange(2020, 2025).toList()}")
}Use Cases
- Lazy paginated API consumption
- Tree and graph traversal
- Mathematical sequence generation
Tags
Related Snippets
Similar patterns you can reuse in the same workflow.
Sequences — Lazy Evaluation for Large Data
Process large datasets efficiently with lazy sequences: generateSequence, yield, and custom iterators.
Best for: Processing large datasets without loading all into memory
Null Safety — Elvis, Safe Call, and let
Master Kotlin null safety: safe calls, Elvis operator, let/also scoping, and smart casts.
Best for: Safe navigation through nullable chains
Data Classes — Copy, Destructure, and Equals
Use data classes for immutable models: auto-generated equals, hashCode, copy, and destructuring.
Best for: Immutable domain models and DTOs
Extension Functions and Properties
Add methods to existing classes without inheritance: extension functions, properties, and generic extensions.
Best for: Adding utility methods to third-party types