wangadu
wangadu

Reputation: 278

how to pass suspend function as explicit parameter to coroutine builder?

I'm looking into launch coroutine builder which takes coroutine code as block: suspend CoroutineScope.() -> Unit. We usually pass the code as lambda. However, I was wondering how to pass this function as explicit parameter to launch function.

coroutineScope {
    launch(block = ::myFunction)
}

suspend fun CoroutineScope.myFunction(): Unit {
    // coroutine code
}

It gives following error

Type mismatch.
Required:
suspend CoroutineScope.() → Unit
Found:
KSuspendFunction0<Unit>

What is it that i'm missing?

Upvotes: 6

Views: 3250

Answers (3)

Jenus Dong
Jenus Dong

Reputation: 304

According to kotlin doc, launch function with parameter is function type: CoroutineScope.() → Unit, is one function type with receiver.

Function types with receiver, such as A.(B) -> C, can be instantiated with a special form of function literals – function literals with receiver.

The same article also noted the following:
Using a callable reference to an existing declaration:
a top-level, local, member, or extension function: ::isOdd, String::toInt,
a top-level, member, or extension property: List<Int>::size,
a constructor: ::Regex
These include bound callable references that point to a member of a particular instance: foo::toString.

but not adaptive to "function literals with receiver".

so one way to make it work:

coroutineScope {
   launch {
      myFunction()
   }
}

Upvotes: 0

Marko Topolnik
Marko Topolnik

Reputation: 200296

The syntax for extension function references is the same as for member functions:

launch(block = CoroutineScope::myFunction)

Upvotes: 2

Glenn Sandoval
Glenn Sandoval

Reputation: 3745

How about this way?

coroutineScope {
    launch(block = myFunction())
}

fun myFunction(): suspend CoroutineScope.() -> Unit = {
    for(i in 3 downTo 1) {
        println("$i")
        delay(1000)
    }
}

Upvotes: 0

Related Questions