What's an idiomatic way to name a function that takes `() -> Unit` vs `suspend () -> Unit`

I’m trying to get up to speed with Kotlin. One of the things I keep hitting snags with is how functions and suspend functions feel like oil and water and don’t mix.

For example if I wanted to wrap some code like this:

time {
  doSomething
}

I apparently can’t have it work regardless of whether doSomething is suspend or not:

package meh;

// I'm not really trying to time code; I'm actually trying to specialize assertFails
// This is just a minimum reproducible program that demonstrates where I'm getting stuck
fun time(fn: () -> Unit) = 0

fun time(fn: suspend () -> Unit) =
  time { /* Overload resolution ambiguity between candidates
          * fun time(fn: () -> Unit): Int
          * fun time(fn: suspend () -> Unit): <ERROR TYPE REF: Ambiguity: time, [meh/time, meh/time]>
          */
    runBlocking {
      fn.invoke()
    }
  }

Is this type erasure and thus intractable, or am I just holding the language wrong? What’s the idiomatic way to work around this? do I call one of them something else, like timeBlocking or timeCoroutine or timeSuspend or blockAndTime or..? do I simply fail to factor out the runBlocking call from every applicable call site?

In case it matters, my team adopted Kotlin version 2.2.

Using runBlocking in such a way is a bad idea. Instead what you want is inline functions. They’re transparent to suspension, meaning that if the caller is suspend, the block will be suspend too, and if not then it won’t be suspend

1 Like

can you please give an example for the inline?

Sure:

inline fun myAssertFails(block: () -> Unit) { 
  try {
    block()
    // error because it didn't fail
  } catch(blah: SomeAssertionType) {
    // failed successfully, 
  }
}

Kotlin 2.2.20 allows you (with language version set to 2.3) to use the suspend keyword on the call side to distinguish both versions, see

Or as video:
https://www.youtube.com/watch?v=QWpp5-LlTqA (at 6:51)

2 Likes