Kotlin sequence concatenation

Your code doesn't copy the sequence elements, and sequenceOf(seq1, seq2).flatten() actually does what you want: it generates a sequence that takes items first from seq1 and then, when seq1 finishes, from seq2.

Also, operator + is implemented in exactly this way, so you can just use it:

(seq1 + seq2).forEach { ... }

The source of the operator is as expected:

public operator fun <T> Sequence<T>.plus(elements: Sequence<T>): Sequence<T> {
    return sequenceOf(this, elements).flatten()
}

You can take a look at the implementation of .flatten() in stdlib that uses FlatteningSequence, which actually switches over the original sequences' iterators. The implementation can change over time, but Sequence is intended to be as lazy as possible, so you can expect it to behave in a similar way.

Example:

val a = generateSequence(0) { it + 1 }
val b = sequenceOf(1, 2, 3)

(a + b).take(3).forEach { println(it) }

Here, copying the first sequence can never succeed since it's infinite, and iterating over (a + b) takes items one by one from a.


Note, however, that .flatten() is implemented in a different way for Iterable, and it does copy the elements. Find more about the differences between Iterable and Sequence here.


Something else you might need to do is create a sequence of sequences:

    val xs = sequence {
        yield(1)
        yield(2)
    }

    val twoXs = sequence {
        yieldAll(xs)
        // ... interesting things here ... 
        yieldAll(xs)
    }

This doesn't do anything that xs + xs doesn't do, but it gives you a place to do more complex things.

Tags:

Kotlin