Hi! maybe someone here can help me, I’ve read this...
# coroutines
f
Hi! maybe someone here can help me, I’ve read this article Coroutine Context and Scope by Roman Elizarov a thousand times and I still don’t get why we need a
CoroutineScope
interface. I get that coroutines builders like
launch
are extension functions on that class, but why can’t they just be extension function on
CoroutineContext
instead?
j
I'm also relatively new to coroutines, so this might not be 100% correct, but here is how I precieve the difference: Consider that in suspending functions the context can always be accessed through the
coroutineContext
value. Let's consider a theoretical example of what if
launch
was an extension function on
CoroutineContext
. Then we could write code like this:
Copy code
suspend fun foo() {
    // Do some work

    coroutineContext.launch {
        delay(1000)
        bar()
    }

    // Do some more work
}
Calling the
foo
method could return, while the code inside the launch method is still active. While this code would work theoretically, it is not ideomatic, because a suspending function is designed to only return when all its work is completed and is not supposed to launch anything else that might complete at a later time. (Paraphrasing the closing statement of the article you mentioned here) To correct the code above we could do something like this:
Copy code
suspend fun foo() = coroutineScope {
    // Do some work

    launch {
        delay(1000)
        bar()
    }

    // Do some more work
}
This would lead to the behavior we expect from a suspending function in that it only returns after all of it's calculations are complete.
❤️ 2
f
Oh Amazing, such a simple explanation 🙂 thank you
that makes total sense
s
Also, a CoroutineScope has a CoroutineContext and a CoroutineScope has behavior (eg cancellation, awaiting child job completions, merging parent CoroutineContext into the child CoroutineContext, etc) that a CoroutineContext doesn't have. A CoroutineContext is just a set of Elements and each Element (eg the Dispatcher, the Job, custom Elements) is-a CoroutineContext itself. You could argue that
coroutineContext[Job]
could serve as the CoroutineScope... In other words, it keeps the two concerns apart: 1. cancellation, awaiting child completion, exception handling; 2. context such as current Dispatcher, custom Elements (like ThreadLocal, but for suspend), name (eg for debugging), etc
👍 1
❤️ 1
f
(eg cancellation, awaiting child job completions,
Right, an example of cancellation would be what
ViewModelScope
does in Android and an example of
child job completions
would be
coroutineScope { ... }
right
👌 1