Inversely related to @toph42 and @michelf's concerns about implicitly awaiting cancellation at scope exit is the current inability to neatly await
many async let
s without caring about their results. This is especially true for async -> Void
functions, but is generally true for any async
function which has side effects you want without the value.
Say you have some async
action functions returning Void
. Sometimes you want to perform them individually, sometimes all at once, in parallel. In all cases you want them to complete. Currently, it's hard to express the await all functionality. async let _
is disallowed. Simply not await
ing the functions results in cancellation. Currently, we must explicitly name and await
every value.
func performAll() async {
async let x = x()
async let y = y()
async let z = z()
_ = await (x, y, z)
}
Or perhaps we could allow async let _
when using @michelf's dangling await
?
func performAll() async {
async let _ = x()
async let _ = y()
async let _ = z()
await
}
Or perhaps allow async let
itself as a scope?
func performAll() async {
await async let {
x()
y()
z()
}
}
Perhaps we could allow async let _
in a particular context?
func performAll() async {
await {
async let _ = x()
async let _ = y()
async let _ = z()
}
}
Even better, perhaps we can drop the async let
when we don't care about the values, and just add the await
scope directly?
func performAll() async {
await {
x()
y()
z()
}
}
I like the look of an await
scope. I wonder if it's generally composable. What rules do we want in it? Perhaps its only new rule is the implicit async let
nature of unawait
ed async
results. Or perhaps that's too much.
Of course, we go the TaskGroup
route and await separate references.
func performAll() async {
await all(x, y, z)
}
func all<T>(_ actions: (() async -> T)...) async {
await withTaskGroup(of: T.self) { group in
for action in actions {
group.async { await action() }
}
}
}
Except that won't work with parameters, barring more wrapping, at which point we've lost most of the convenience.
Perhaps this isn't that big of an issue. It just seems awkward to have a brand new feature that doesn't handle such a case very elegantly.