TIL about Swift `async let` and I really want it: ...
# language-evolution
j
s
Isn't this already possible using Deferrable<>
async let someAsyncVar = getSomeVar()
async let otherAsyncVar = getSomeOtherVar()
followed by
await [ try someAsyncVar, otherAsyncVar]
possible in kotlin with
val someAsyncVar = async { getSomeVar() }
val otherAsyncVar = async { getSomeOtherVar() }
followed by
listOf(someAsyncVar, otherAsyncVar).awaitAll()
? Or do you like the syntactic sugar of the swift code?
j
Sure, just like the article says. But it is significantly less clear than the code that uses the compiler to do that.
r
Could you clarify what is less clear? Perhaps it's my lack of familiarity with Swift, but I find
val x = async { foo() }
is more clear than
async let x = foo()
j
It's the part where you have to do specific awaits later on.
r
Ah, my bad. Thanks.
j
And in Swift the derived operations are also automatically async.
From the example: `
Copy code
let dish = Dish(ingredients: await [try veggies, tofu])
is yet another async operation, even though it doesn't say so.
s
Don't you have to do await later on in swift as well?:
await [ try someAsyncVar, otherAsyncVar]
j
True.
As you pointed out, the syntactic sugar is a big part of the readability.
s
I see the only difference is the keyword
await
in Swift vs the library function call
await()
or
awaitAll()
in Kotlin.
j
And the automatic derived operations.
s
Yup; it's keywords vs (library) function calls.
One of the design principles in Kotlin is to favor function calls (easier to extend/augment/add) over keywords. Overall, I like that decision
r
I think I prefer that in Kotlin that is explicitly NOT async:
Copy code
val dish = Dish(ingredients = listOf(veggies, tofu).awaitAll())
And can be made async easily by wrapping it in an async block like with the ingredients calls. It feels consistent.
Granted, it would be prettier with collection literal syntax, but that's another issue 🙂
j
You can just
awaitAll(one, two, three)
☝️ 1
w
I've worked on Swift language support, and I really like the high level language design of Swift. But I'd argue that Swift's language feature often aren't that coherent (sorry, this statement became irrelevant after I removed my whole complaint about some lacking structured concurrency support :) ). Imho the pro is that this naturally makes people use asynchronous operations more correctly in terms of structured concurrency. In an ideal Kotlin world, the vast majority of your `async`s live inside of a
coroutineScope { }
block, and don't escape it. In reality this is often not the case. People frequently do things like
viewModelScope.async { }
, or use other scopes that are not bound to their lexical scope. This causes many footguns. The nice thing is that Swift enforces this in their
async let
design. But I personally prefer kotlin's approach, and I much prefer to read:
launch { mySideEffect() }
over:
async let _ = mySideEffect()
. And
launch
is more than 10x!! as common than
async
in Kotlin code.
👍 1