Skip to content

Instantly share code, notes, and snippets.

@happy-bracket
Created July 11, 2019 12:16
Show Gist options
  • Save happy-bracket/ab0714bb6929a6ff817ebf1288bccaa3 to your computer and use it in GitHub Desktop.
Save happy-bracket/ab0714bb6929a6ff817ebf1288bccaa3 to your computer and use it in GitHub Desktop.
Nullable Comprehension
import kotlin.coroutines.*
import kotlin.coroutines.intrinsics.COROUTINE_SUSPENDED
import kotlin.coroutines.intrinsics.suspendCoroutineUninterceptedOrReturn
class NullableComprehension<R> : Continuation<R> {
override val context: CoroutineContext = EmptyCoroutineContext
private var internalResult: R? = null
/**
* Asserts that the value is not null or interrupts `coerceNull` computation completely and returns null.
*/
suspend fun <T> T?.coerce(): T {
return suspendCoroutineUninterceptedOrReturn {
if (this != null) {
it.resume(this)
}
COROUTINE_SUSPENDED
}
}
override fun resumeWith(result: Result<R>) {
internalResult = result.getOrThrow()
}
fun getResult(): R? = internalResult
}
/**
* Creates computational context in which you can [NullableComprehension.coerce] nullable types
*/
fun <R> coerceNull(block: suspend NullableComprehension<R>.() -> R): R? {
val context = NullableComprehension<R>()
block.startCoroutine(context, context)
return context.getResult()
}
fun sample() {
val a: Int? = 2
val b: Int? = 3
val c: Int = 5
val d: Int? = null
val res: Int? = coerceNull {
a.coerce() + b.coerce() + c + d.coerce()
}
println(res) // null
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment