Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Understanding Kotlin's yield function

I don't see a very clear definition of the yield function in Kotlin.

Example in the link above doesn't mention much but the following,

val sequence = sequence {     val start = 0     // yielding a single value     yield(start)     // yielding an iterable     yieldAll(1..5 step 2)     // yielding an infinite sequence     yieldAll(generateSequence(8) { it * 3 }) }  println(sequence.take(7).toList()) // [0, 1, 3, 5, 8, 24, 72] 

But the above example doesn't point out the significance of yield.

  • What does it mean that it is a suspending function?
  • In what scenarios can it be advantageous?
like image 237
Ahmed Avatar asked Mar 12 '19 20:03

Ahmed


People also ask

What does yield do in Kotlin?

Yields a value to the Iterator being built and suspends until the next value is requested.

What is coroutine yield?

Yields a thread (or thread pool) of the current coroutine dispatcher to other coroutines to run. If the coroutine dispatcher does not have its own thread pool (like Dispatchers. Unconfined) then this function does nothing, but checks if the coroutine Job was completed. This suspending function is cancellable.

How coroutine is implemented?

A coroutine internally uses a Continuation class to capture the contexts for its execution. Then the dynamic aspect is modeled as a Job class. The use of async usually creates a Deferred job, which is a subclass of the Job class. The CoroutineContext type is required for a coroutine to execute.

What is sequence in Kotlin?

A sequence is a container Sequence<T> with type T. It's also an interface, including intermediate operations like map() and filter(), as well as terminal operations like count() and find(). Like Streams in Java, Sequences in Kotlin execute lazily.


1 Answers

You can think of yield() as "return, and next time start from where you stopped":

val sequence = sequence {     val start = 0     yield(start) // first return     yieldAll(1..5 step 2) // if called again, will start from here     yieldAll(generateSequence(8) { it * 3 }) // if called more that six times, start from here } 

It creates state machine and stuff, but you can translate it to something like following in Java:

class Seq {     private AtomicInteger count = new AtomicInteger(0);     private int state = 0;          public int nextValue() {         if (count.get() == 0) {            return state;         }         else if (count.get() >= 1 && count.get() <= 5) {            state += 2;            return state;         }         else {            state *= 3;            return state;         }     } } 

In Java class we maintain explicit state by having two variables: count and state. Combination of sequence and yield allow this state to be maintained implicitly.

Note that yield() is a suspending function, so it may be invoked only from another suspend function or from within a coroutine.

like image 97
Alexey Soshin Avatar answered Oct 09 '22 22:10

Alexey Soshin