How do I infinitely repeat a sequence in Kotlin?

Update: coroutines are no longer experimental as of Kotlin 1.3! Use them as much as you like :)


If you allow the use of coroutines you can do this in a pretty clean way using sequence:

an infinite amount of times

fun <T> Sequence<T>.repeat() = sequence { while (true) yieldAll(this@repeat) }

Note the use of a qualified this expression this@repeat - simply using this would refer to the lambda's receiver, a SequenceScope.

then you can do

val intArray = intArrayOf(1, 2, 3)
val finiteIntSequence = intArray.asSequence()
val infiniteIntSequence = finiteIntSequence.repeat()

println(infiniteIntSequence.take(10).toList())
// ^ [1, 2, 3, 1, 2, 3, 1, 2, 3, 1]

a finite amount of times

fun <T> Sequence<T>.repeat(n: Int) = sequence { repeat(n) { yieldAll(this@repeat) } }

To avoid using the experimental coroutines, use:

generateSequence { setOf("foo", 'b', 'a', 'r') }
  .flatten() // Put the Iterables' contents into one Sequence
  .take(5) // Take 5 elements
  .joinToString(", ")

// Result: "foo, b, a, r, foo"

or alternatively, if you want to repeat the entire collection a number of times, just take before flattening:

generateSequence { setOf("foo", 'b', 'a', 'r') }
  .take(5) // Take the entire Iterable 5 times
  .flatten() // Put the Iterables' contents into one Sequence
  .joinToString(", ")

// Result: "foo, b, a, r, foo, b, a, r, foo, b, a, r, foo, b, a, r, foo, b, a, r"

For the original question's IntArray, the array first must be converted to an Iterable<Int> (otherwise flatten() isn't available):

val intArray = intArrayOf(1, 2, 3)

generateSequence { intArray.asIterable() }
  .flatten()
  .take(10)
  .joinToString(", ")

// Result: "1, 2, 3, 1, 2, 3, 1, 2, 3, 1"

Furthermore, other types of Array, e.g. ByteArray or LongArray, as well as Map are not Iterable, but they all implement the asIterable() method like IntArray in the example above.


I think this is pretty clear:

generateSequence(0) { (it + 1) % intArray.size }
        .map { intArray[it] }
        .forEach { println(it) }