下記のようにすることで、Sequence
を返す関数を再帰で実装できる。
再帰だが、suspend 関数(コルーチン)で実装されているので処理が平坦化され、
スタックオーバーフローは起こらない。
(末尾再帰の最適化が行われているのではない。)
フィボナッチ数列を表す Sequence を返す関数を再帰で実装した例
/**
* フィボナッチ数列を返す。
*
* ```
* fibonacciSequence().take(10).toList() // -> [0, 1, 1, 2, 3, 5, 8, 13, 21, 34]
* ```
*/
fun fibonacciSequence(): Sequence<Long> {
return sequence {
val a = 0L
val b = 1L
yield(a)
yield(b)
yieldFibonacciSequenceAfter(a, b)
}
}
/**
* [a], [b] 以降のフィボナッチ数を [SequenceScope.yield] する。
*/
private suspend fun SequenceScope<Long>.yieldFibonacciSequenceAfter(a: Long, b: Long) {
val c = a + b
yield(c)
yieldFibonacciSequenceAfter(b, c)
}
/以上