And this is exactly the point of the coroutines design. If you don’t use threading, coroutines, etc., just the classic code and you need to run one operation after another, then you do:
doSomething()
doSomethingElse()
If you use coroutines and you need to run one operation after another, then you do:
doSomething()
doSomethingElse()
How is this counter-intuitive and it would be more natural to use words like async/await to accomplish the same kind of behavior?
I see it exactly the opposite to you. From your description (I don’t know Swift), Swift focuses on what is happening inside the function, focuses on its implementation details, we need to consider if function is asynchronous or not and use it accordingly. Kotlin focuses on the fact that we called a function and we don’t even have to know if it is asynchronous or not - the code is exactly the same.
Completely agree with you. However, note the Swift design is actually pretty similar, though the async/await terminology is confusing. Adding the async key word to a function is just like marking a function with suspend – it indicates the function suspends/resumes (even the Swift docs describe it this way).
I’m not a Swift expert either, but I think the main difference is that in Swift you as a developer must mark a suspension point with await, OR assign the result to an async let variable which would be similar to using val deferred = async { … } in Kotlin. I’m not positive how async let plays with structured concurrency. I don’t think Swift’s structured concurrency story is as comprehensive as Kotlin’s – see this thread for example.
The Swift approach seems easier to understand for beginners because devs don’t need to worry about things like scopes when doing a basic async/async let, but harder to correctly program a larger application because devs would need to know when to opt out of the implicit behaviors.