Sam Garfinkel
03/25/2020, 2:32 PMCoroutineScope (with a delegate) on a class so that you can use Deferred as the value of its properties? This is kind of useful for creating lazily computed properties that are backed by network I/O (I’m using Ktor):
class Foo(val client: HttpClient) : CoroutineScope by GlobalScope {
val bar: Deferred<String> by lazy {
async {
client.get<String>("<https://www.example.com>")
}
}
}Sam Garfinkel
03/25/2020, 2:33 PMbar but I only want to compute bar when needed.streetsofboston
03/25/2020, 2:33 PMstreetsofboston
03/25/2020, 2:34 PMAdam Powell
03/25/2020, 2:34 PMsuspend fun, not a Deferred. Deferred is the implementation detail hereSam Garfinkel
03/25/2020, 2:35 PMsuspend fun would compute the result each time. How would I implement the lazy functionality?streetsofboston
03/25/2020, 2:35 PMsuspend fun can call await() on the deferredstreetsofboston
03/25/2020, 2:35 PMAdam Powell
03/25/2020, 2:35 PMDeferred because then anyone can .cancel() it 🙂Sam Garfinkel
03/25/2020, 2:36 PMsuspend fun foo() = client.get<String>("<https://www.example.com>") would compute it each time.Sam Garfinkel
03/25/2020, 2:36 PMclient.get since it’s expensive.Adam Powell
03/25/2020, 2:36 PMsuspend fun foo() = privateDeferredVal.await() would not.Sam Garfinkel
03/25/2020, 2:38 PMval private? I did that, I think I just forgot that in the example. So updated example:
private val bar: Deferred<String> by lazy {
GlobalScope.async {
client.get<String>("<https://www.example.com>")
}
}
Is this the correct design?Adam Powell
03/25/2020, 2:39 PMGlobalScope into a private val passed to the constructor insteadSam Garfinkel
03/25/2020, 2:40 PMAdam Powell
03/25/2020, 2:41 PMGlobalScope it's probably wrong and you'll be on the right track more often than not 🙂 you also generally want your callers to be able to provide scopes to work in rather than hardcoding themSam Garfinkel
03/25/2020, 2:42 PMAdam Powell
03/25/2020, 2:46 PMAdam Powell
03/25/2020, 2:46 PMSam Garfinkel
03/25/2020, 2:49 PMbar in that example, from suspendable functions.Sam Garfinkel
03/25/2020, 2:49 PMSam Garfinkel
03/25/2020, 2:50 PMAdam Powell
03/25/2020, 2:51 PMSam Garfinkel
03/25/2020, 2:57 PMzak.taccardi
03/25/2020, 5:49 PMby lazy { .. }. Try async(start = CoroutineStart.LAZY) { .. } instead
This will avoid executing the coroutine until .await() is calledSam Garfinkel
03/25/2020, 6:28 PMAdam Powell
03/25/2020, 7:18 PMstreetsofboston
03/25/2020, 7:20 PMasync until the bar is accessed for the first time, not kick it off immediately during the initialization of FooAdam Powell
03/25/2020, 8:34 PM