`async let` initializer ergonomics

In converting an existing codebase (not large, but with a variety of completion-handler-based asynchronicity strategies), I ran into a couple of ergonomic issues. I don't recall these being discussed during the pitch phase of Swift concurrency, so I'm offering them as ideas for general discussion here and in related forum threads.

Consider a scenario where I would want to use something like this:

async let result1 = someAsyncFunction1()
async let result2 = someAsyncFunction2()
async let result3 = someAsyncFunction3()
…
await result1
await result2
await result3

It sometimes turns out that I only need result2 conditionally, depending on some Boolean condition. That's a bit awkward to handle with async let.

What I'd like to do for result2 is use this variation of an existing pattern:

async let result: ResultType?
if someCondition {
   result = someAsyncFunction2()
}
else {
   result = nil
}
…
await result2

This is not beautiful syntax, but it's at least a known pattern (ignoring the async).

Is there some technical problem with having this form with async let?

Edit: I forgot to include my other example:

async let result: ResultType?
do {
   result = try someAsyncFunction2()
}
catch {
   result = nil
}
…
await result2

Of course, I can use try? instead when it's this simple, but it's gets harder when there's more inside the do block.

2 Likes