| Author here. > But please don't mislead readers that structured concurrency solves this. It absolutely does. The reason is that, in structured concurrency, when a function spawns a thread, you can expect that that thread is joined before the function returns. For callers, this means that they don't have to worry about whether the function they are calling spawns threads or not; they just call the function, and the function does its thing. It is the same principle as standard control flow constructs: they use `goto` underneath, but you don't need to worry about the use of `goto` because they guarantee that execution will always end up at the same place afterward (barring early returns and things like that). So when I say that structured concurrency does not suffer from the colored function problem, what I am saying is that callers, and programmers, do not need to care what functions do underneath when they are called. Also, structured concurrency solves the function coloring problem because you can use any function, whether it spawns threads or not, as first-class functions, or function pointers, and it all works without needing any special code, or work, or compiler trickery. |
Thanks for clarifying what you meant with your original comment in the article. I completely agree that this is a very big advantage, as opposed to not using structured concurrency.
However, it seems that you are conflating two things with this assertion. For example you say:
> The reason is that, in structured concurrency, when a function spawns a thread, you can expect that that thread is joined before the function returns
While structured concurrency gives you this guarantee, this is orthogonal to whether a function the thread runs is "red" or "blue".
"Red" functions exist in a language because you want blocking to happen on userland so it's cheap to unschedule the task that is blocking.
Structured concurrency doesn't remove "red" functions from a language. They do make the ergonomics of using such functions much easier on the caller e.g. python's trio library [0].
To actually "remove Red functions from the language" you can make the user think they're just using plain "blue" function techniques for blocking.
Go achieves this by only allowing use userland threading.
Java's project Loom [1] achieves this by making common suspension/yielding points (e.g. IO) compatible with both userland and OS threading.
To me, this is what solves the colouring problem i.e. you only have one colour and keep using and writing your code as you always have been.
Structured concurrency, much like you said, is the added bonus that helps reasoning about the lifecycle of tasks a function may or may not spawn.
[0] - https://trio.readthedocs.io/en/stable/index.html
[1] - https://wiki.openjdk.java.net/display/loom/Main
(edit note: my phone messed up quoting)