Range Over Iterators in Kotlin
On this page
Starting with version 1.23, Go has added support for iterators, which lets us range over pretty much anything!
Let’s look at the List type from the previous example again. In that example, we had an AllElements method that returned a slice of all elements in the list. With Kotlin iterators (known as sequences), we can do it better - as shown below.
Code Example
class List<T> {
private var head: Element<T>? = null
private var tail: Element<T>? = null
private class Element<T>(val value: T, var next: Element<T>? = null)
fun push(value: T) {
if (tail == null) {
head = Element(value)
tail = head
} else {
tail!!.next = Element(value)
tail = tail!!.next
}
}
fun all(): Sequence<T> = sequence {
var current = head
while (current != null) {
yield(current.value)
current = current.next
}
}
}
fun genFib(): Sequence<Int> = sequence {
var a = 1
var b = 1
while (true) {
yield(a)
val next = a + b
a = b
b = next
}
}
fun main() {
val lst = List<Int>()
lst.push(10)
lst.push(13)
lst.push(23)
for (e in lst.all()) {
println(e)
}
val all = lst.all().toList()
println("all: $all")
for (n in genFib()) {
if (n >= 10) break
println(n)
}
}Explanation
Define the List Class
We start by defining a generic List class to store elements.
class List<T> {
private var head: Element<T>? = null
private var tail: Element<T>? = null
private class Element<T>(val value: T, var next: Element<T>? = null)
// Other methods...
}Push Method
The push method adds an element to the end of the list.
fun push(value: T) {
if (tail == null) {
head = Element(value)
tail = head
} else {
tail!!.next = Element(value)
tail = tail!!.next
}
}All Method
The all method returns a Kotlin sequence, which is an iterator that lazily evaluates the elements in the list.
fun all(): Sequence<T> = sequence {
var current = head
while (current != null) {
yield(current.value)
current = current.next
}
}Generate Fibonacci Sequence
We define a genFib function that generates an infinite sequence of Fibonacci numbers using a Kotlin sequence.
fun genFib(): Sequence<Int> = sequence {
var a = 1
var b = 1
while (true) {
yield(a)
val next = a + b
a = b
b = next
}
}Main Function
In the main function, we create a List, add elements to it, and then iterate over them using the all method.
fun main() {
val lst = List<Int>()
lst.push(10)
lst.push(13)
lst.push(23)
for (e in lst.all()) {
println(e)
}
val all = lst.all().toList()
println("all: $all")
for (n in genFib()) {
if (n >= 10) break
println(n)
}
}This code demonstrates how to iterate over custom data structures using Kotlin sequences, providing a modern and idiomatic way to handle iteration in Kotlin.