I’m working on a toy implementation of structured concurrency (as a library) for the Lua programming language.
There’s the design decision about async/await and function coloring, though here I’m limited because I’ll not add new language syntax. Lua has only coroutines, and no built-in scheduler or notion of concurrency. (In contrast with Python, nice to start from a clean slate.)
So I reread https://lukasa.co.uk/2016/07/The_Function_Colour_Myth/, and it’s clear that using coroutines without marking async definitions or calls is an option, though there is utility to marking. I’m familiar with Python’s choices as well as Kotlin’s.
Summary of function coloring options:
symmetric async / await - i.e. markers for both definitions and calls, as Python does. Typically part of the language syntax, though decorators could be used for definitions. Unfortunately for Python, even though async / await is part of the language, omitting
awaitis not caught at compile time.
- asymmetric async / await - marker on only definitions or usages, e.g. Kotlin only marks definitions. The argument by Kotlin’s structured concurrency author is that the IDE can flag awaitable expressions in the code. However, I think the reasoning is flawed because we aren’t always viewing code through an IDE (code reviews, code snippets in the wild, etc.). Especially for single-OS-thread scenarios where there is no implicit context switch, it’s essential to know the points of explicit context switch (and corresponding atomicity between those points) to reason about the code.
naming convention only - for Lua, I’m leaning toward prefixing all async definitions with
async_. Obviously the marking is equally visible at usage sites. This naming applies to the “trio” library as well-- so
async_open_nursery(), etc. Perhaps static or runtime checks could be built upon the naming convention.
- nothing - e.g. golang? Like (2), but worse.