Home > Software engineering >  What is the Kotlin equivalent of Python generators?
What is the Kotlin equivalent of Python generators?

Time:06-10

If I have a python generator function, let's say this one:

def gen():
    x = 0
    while (true):
        yield x
        x  = 1

This function remembers its current state, and every time you call gen(), yields a new value. Essentially, I would like a Kotlin sequence which can remember its state.

CodePudding user response:

def gen():
    x = 0
    while (true):
        yield x
        x  = 1 

This function remembers its current state, and every time you call gen(), yields a new value.

This is incorrect. Every time you call gen() you get a new "generator object" whose state is independent of any other generator object created by this function. You then query the generator object to get the next number. For example:

def demo():
    numbers = gen()  # 'gen()' from your question
    for _ in range(0, 3):
        next_number = next(numbers)
        print(next_number)


if __name__ == '__main__'
    demo()
    print()
    demo()

Output:

0
1
2

0
1
2

As you can see, the sequence of numbers "starts over" when you call gen() again (though if you kept a reference to the old generator object it would continue from 2, even after calling gen() again).

In Kotlin, you can use the kotlin.sequences.iterator function. It creates an Iterator which lazily yields the next value, just like a Python generator object. For example:

fun gen() = iterator {
    var x = 0
    while (true) {
        yield(x)
        x  
    }
}

fun demo() {
    val numbers = gen()
    repeat(3) {
        val nextNumber = numbers.next()
        println(nextNumber)
    }
}

fun main() {
    demo()
    println()
    demo()
}

Which will output:

0
1
2

0
1
2

Just like the Python code.

Note you can do the essentially the same thing with a Kotlin Sequence, you just have to convert the Sequence into an Iterator if you want to use it like a Python generator object. Though keep in mind that Kotlin sequences are meant more for defining a series of operations and then lazily processing a group of elements in one go (sort of like Java streams, if you're familiar with them).

CodePudding user response:

As stated before in the comments https://kotlinlang.org/docs/sequences.html are the answer, and you don't even need an iterator. You can generate sequence using https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.sequences/generate-sequence.html

and here is a little playground witch produces similar sequence as your generator https://pl.kotl.in/LdboRzAzr

  • Related