Prime number sequence supporting repeated iteration I'm a long-time Java programmer, but recently I decided to give Kotlin a try.  So far, I'm loving the language features, it feels much more expressive than what I'm used to.  As practice, I wrote this function that produces a repeatable sequence of prime numbers (i.e. the sequence can be iterated multiple times, and will make use of results from past iterations to speed up future iterations).  It feels pretty solid to me, but I'm wondering how it would look to a Kotlin veteran - are there language features that I'm not taking full advantage of, or conventions that I should be following?
One question I have in particular is regarding top-level function vs. subclass; here I chose to implement a top-level function primeSequence(): Sequence&lt;Long&gt; that returns an object, but I could have just about as easily implemented a class PrimeSequence : Sequence&lt;Long&gt;.  Is there a good rule of thumb for when to use one or the other?
fun primeSequence(): Sequence&lt;Long&gt; = object: Sequence&lt;Long&gt; {
    private val knownPrimes: MutableList&lt;Long&gt; = arrayListOf(2L, 3L)

    private fun Long.isMultipleOf(n: Long) = (this%n == 0L)
    
    private fun Long.isPrime() = knownPrimes
            .takeWhile { it*it &lt;= this }
            .none { this.isMultipleOf(it) }

    override fun iterator(): Iterator&lt;Long&gt; = object: Iterator&lt;Long&gt; {
        private var lastPrime: Long? = null

        override fun hasNext() = true

        override fun next(): Long {
            val nextPrime = when(val lastPrime = this.lastPrime) {
                null -&gt; 2L
                2L -&gt; 3L
                else -&gt; {
                    if (knownPrimes.last() &gt; lastPrime ) {
                        knownPrimes[knownPrimes.binarySearch(lastPrime) + 1]
                    } else {
                        val np = generateSequence(lastPrime+2) { it+2 }
                                .first { it.isPrime() }
                        knownPrimes.add(np)
                        np
                    }
                }
            }
            this.lastPrime = nextPrime
            return nextPrime
        }
    }
}
I don't like the idea of returning an inline object that inherits Sequence&lt;Long&gt; like this. Kotlin has several features to help you build stuff, including one for sequences.
Using the fantastic power of the sequence builder in Kotlin, which underneath the surface is using a suspendable function internally, we can yield numbers one by one instead of implementing an Iterator.
We can rewrite your code to use an outer object to keep the global state in, and then use a function to generate the sequence.
object Primes {
    private val knownPrimes: MutableList&lt;Long&gt; = mutableListOf(2L, 3L)
    private fun Long.isMultipleOf(n: Long) = (this % n == 0L)

    private fun Long.isPrime() = knownPrimes
            .takeWhile { it * it &lt;= this }
            .none { this.isMultipleOf(it) }

    fun sequence(): Sequence&lt;Long&gt; {
        var lastPrime: Long? = null
        return sequence {
            while (true) {
                val nextPrime = when(val actualLastPrime = lastPrime) {
                    null -&gt; 2L
                    2L -&gt; 3L
                    else -&gt; {
                        if (knownPrimes.last() &gt; actualLastPrime) {
                            knownPrimes[knownPrimes.binarySearch(actualLastPrime) + 1]
                        } else {
                            val np = generateSequence(actualLastPrime + 2) { it+2 }
                                .first { it.isPrime() }
                            knownPrimes.add(np)
                            np
                        }
                    }
                }
                lastPrime = nextPrime
                yield(nextPrime)
            }
        }
    }
}