Давайте рассмотрим пример, в котором вы можете сгенерировать следующий элемент последовательности, но вы не видите простого способа реализации итератора Java.
fun fibonacci() = sequence {
var a_0 = 1
var a_1 = 1
// this sequence is infinite
while(true) {
val a_n = a_0 + a_1
a_0 = a_1
a_1 = a_n
//this is a suspend function call
yield(a_0)
}
}
В примере используется функция yield
для возврата следующего элемента последовательности. Функция является примером функции suspend
в Kotlin. Вызов функции приостанавливает выполнение блока sequence{..}
, поэтому стек вызовов свободен.
Допустим, мы делаем следующее
fibonacci().take(10).forEach{
println(it)
}
Каждая итерация цикла forEach
возобновит блок sequence{..}
с предыдущего вызова функции yield
и позволит ему перейти к следующему вызову функции yield
. Поток выполнения будет смешивать итерации цикла forEach
с оценкой блока sequence{..}
. Вы можете попробовать написать то же, что и Java Iterator
, чтобы почувствовать, что компилятор Kotlin делает за кулисами.
suspend
функции в Kotlin сделаны минималистичными на языке и на стандартной библиотечной стороне, остальные могут быть реализованы в библиотеках. Я рекомендую проверить библиотеку kotlinx.coroutines
на предмет большего количества внутренностей, примеров и документации
https://github.com/Kotlin/kotlinx.coroutines