Reputation: 5133
The following two method contain the same functionality, the only difference is that one is suspendable and the other isn't (same for parameters).
How can I extract the implementation and reuse it for both functions?
fun validationWrapper(supplier: () -> Unit) = try {
supplier.invoke()
} catch (ex: Exception) {
when (ex) {
is IllegalArgumentException, is IllegalStateException -> throw ValidationException(ex.message!!)
else -> throw ex
}
}
suspend fun validationWrapper(supplier: suspend () -> Unit) = try {
supplier.invoke()
} catch (ex: Exception) {
when (ex) {
is IllegalArgumentException, is IllegalStateException -> throw ValidationException(ex.message!!)
else -> throw ex
}
}
I could keep only the suspendable function but that would mean I should use a runBlocking
each time I use it.
Upvotes: 1
Views: 82
Reputation: 37720
Keep the non-suspend version and make it inline
. This solves the problem because the inlined lambda can then contain suspending calls without being declared suspend
itself. It is how most of the Kotlin stdlib does this (forEach
, map
, etc.):
inline fun validationWrapper(supplier: () -> Unit) = try {
supplier.invoke()
} catch (ex: Exception) {
when (ex) {
is IllegalArgumentException, is IllegalStateException -> throw ValidationException(ex.message!!)
else -> throw ex
}
}
Also, it is generally useful for higher-order functions that take lambdas to be declared inline
, because it avoids extra costs of lambda instances.
Upvotes: 1