Is there a coroutine equvalent for `lazy`? I'm not...
# coroutines
t
Is there a coroutine equvalent for
lazy
? I'm not looking for
async
. All I want is execution in the current coroutine, if the value was not yet computed.
m
Why can't you use
lazy
?
t
Because I want the provider function to be suspendable. Something like:
Copy code
val userToken = suspendableLazy {
    getUserTokenFromServerWithPotentiallyLongIO()
}

val user = User(userToken.get())
....
val x = getXForUser(userToken.get())
j
perhaps lateinit is good enough?
b
Deferred
is all you need:
Copy code
suspend fun currentTimeStamp(): Long  {
    delay(2000L) // simulate background operation
    return System.currentTimeMillis()
}

@Test
fun lazyTest() = runBlocking {
    val time = async {currentTimeStamp() }
    println(time.await())
    delay(2000L)
    println(time.await())
}
second await will print same value
you can put deferred as property in your class if class implements `CoroutineScope`:
Copy code
class ScopePlayground : CoroutineScope {

    private val job = SupervisorJob()
    override val coroutineContext: CoroutineContext
        get() = job + Dispatchers.Default

    private val time = async { currentTimeStamp() }
// rest of the code
t
Thanks for the reply, but the
CoroutineScope
is not available during definition time in my case. And I don't want to pass it on every invocation as it is basically unnecessary for what I want to achieve. I went with the following solution for now:
Copy code
interface SuspendableProvider<T> {
    suspend fun get(): T
}

fun <T : Any> suspendableLazy(provider: suspend () -> T) = object : SuspendableProvider<T> {
    val mutex = Mutex()
    lateinit var computed: T

    override suspend fun get() = mutex.withLock {
        if (!this::computed.isInitialized) {
            computed = provider()
        }

        computed
    }
}
j
sounds like a lazy contextkey
t
As in coroutineContext[key]? How so?