Suspendable functions and coroutines

Every language makes us worry about designating async boundaries. Keywords or types like async, await, promise, future, channel, task, parallel stream, parallel collection, concurrent collection, observable, actor etc all mark async boundaries. Synchronous code replaces them all with strict (eagerly evaluated) collections and values.

Making code asynchronous is equivalent to adding async boundaries. Similarly, making code synchronous is equivalent to removing async boundaries (e.g. by fully awaiting on them in a single place). You always need to do some code refactoring to change between those two styles.

The question is which primitives and which syntax should we choose for doing async programming. I suspect one of the main obstacles for convenient async programming syntax is return keyword semantics in Scala. Right now it returns from nearest enclosing method (source code wise, not generated code wise). This is done by throwing and catching exceptions when done inside a function. It breaks referential transparency, refactoring, is inefficient, suprising and now ultimately deprecated ( Deprecated: Nonlocal Returns ). Is properly working return keyword vital for async programming? What do you think?

2 Likes