Hey, I'm just reading the introduction to Channels...
# coroutines
m
Hey, I'm just reading the introduction to Channels. Immediately after reading the first example with a function which creates a Chanel, I asked myself why they use an extension function for the CoroutineContext instead of just marking the function a suspend function. Original example:
Copy code
fun CoroutineScope.produceSquares(): ReceiveChannel<Int> = produce {
    for (x in 1..5) send(x * x)
}
What I would expect:
Copy code
suspend fun produceSquares(): ReceiveChannel<Int> = produce {
    for (x in 1..5) send(x * x)
}
Later in the document you can find:
All functions that create coroutines are defined as extensions on CoroutineScope, so that we can rely on structured concurrency to make sure that we don't have lingering global coroutines in our application.
But doesn't the
suspend
keyword does exactly that? It makes the current CoroutineContext implicitly available to the called function?
o
CoroutineContext
!=
CoroutineScope
. Scope is generally used to start new coroutines, like with
produce
. It's hard for me to word the exact reason why
suspend
doesn't implicitly have it available, but it has to do with structured concurrency. If you want a CoroutineScope in
suspend
functions, you typically use the
coroutineScope
function
m
Okay, thanks.
z
It's also because the function doesn't actually suspend, it always returns immediately. Using a scope receiver indicates (and enforces) this. In general, functions that return channels or flows shouldn't suspend, since their return type already expresses asynchrony.
👍 1
m
Somehow that makes sense 😂