What makes Iterable.map work with suspend functions?

Viewed 1679

In general, suspend funs cannot be used in place of normal funs. If you try to call a suspend fun directly from a normal fun, you will get a compile-time error.

This blog post mentions that you can do a concurrent map in Kotlin by writing

list.map { async { f(it) } }.map { it.await() }

Why does the second map compile? You can't generally pass a suspend fun in place of a fun. Is it

  • that map is an inline fun and that the suspension is automatically inferred "upstream"
  • that map is special cased somehow by Kotlin
  • something else?
1 Answers

that map is an inline fun and that the suspension is automatically inferred "upstream"

Yes. Suspend funs are checked after inlining. I can't see an explicit mention of this in documentation, but there is one in the Coroutines KEEP:

Note: Suspending lambdas may invoke suspending functions in all places of their code where a non-local return statement from this lambda is allowed. That is, suspending function calls inside inline lambdas like apply{} block are allowed, but not in the noinline nor in crossinline inner lambda expressions. A suspension is treated as a special kind of non-local control transfer.

Related