Article
Suspending Lambdas in Kotlin
November 11, 2020
suspend { ... }
to create a suspending lambda. That is all.When first working with Kotlin coroutines you will quickly come across the suspend
keyword as a means of marking a function as a “suspending function”. For example:
There are times, however, where you will run into more exotic usages. Consider the following preview function from the coroutines core library:
This extension allows for a typical suspending function to be converted to a Flow
. In this case, the suspend
keyword is being used to describe a functional type which is suspending:
This intuitively makes some sense: just as there is a way to define non-suspending functional types like () -> T
, there should also be a way to define suspending ones. The example given in the documentation for the function above provides one way to get a reference to a function of such a type. Given a no-argument suspending function like
A function of type suspend () -> R
can then be returned via the function reference ::remoteCall
. This is simply the suspending equivalent to the non-suspending case. For example, given
the function reference ::nonSuspendingCall
will be of type () -> R
.
The question, however, becomes: how does one define such a functional type using a lambda? Consider the following suspending function:
The function reference ::downloadFile
has a type of suspend (String) -> File
and would not, for example, be suitable for use with the asFlow
helper. You may be tempted to try and use the helper method by defining a lambda as follows:
This does not compile, though, when called outside a suspending function and will result in the error message:
Suspend function ‘downloadFile’ should be called only from a coroutine or another suspend function
You may have guessed that verbosity can save the day here if we explicitly denote the lambda as having the suspending type we are looking for:
This does, in fact, work but it is also not entirely satisfying: as Kotlin developers we are spoiled by type inference and feel entitled that it should exist for this case as well. Luckily there is a way to give us the result we crave with another very interesting usage of the suspend
keyword in which it is prepended to the lambda definition:
The syntax suspend { … }
results in a “suspending lambda” and produces a function of type suspend () -> T
, which is exactly what we are looking for. With this syntax, suspending lambdas can take their place alongside their non-suspending siblings as another valuable tool in our coroutines (and Kotlin) toolbox.
Brian writes suspending………………lambdas at Livefront .