|
|
|
|
|
by jcranmer
20 days ago
|
|
What I like least about this article is that it's completely soured the entire context of asynchronous programming. Invariably, any time someone discusses design of an async functionality, function coloring is brought up, with almost no analysis as to how it applies and why it's a good or bad thing. (Ironically, I probably see more in-depth analysis these days as to why this article isn't apropos than why it is when this happens.) It's just reduced to "anything that makes a separation between async and sync is function coloring and that's automatically bad." The existence of any sort of trade-off, or really, the entire meat of the article, is just completely ignored. One thing that can be better called out is that this issue of function coloring isn't just an async problem. Exceptions cause function coloring--and not just Java's controversial checked exceptions. An infallible/fallible domain split is function coloring. Javascript's async handling is called out not because it's doing the function coloring but because--in 2015--the tools that existed for dealing with async code in JS libraries were really, really bad, largely reliant on callback hell. Promises and the async/await keyword fix most of the issues, and the ones that aren't fixed boil down to the fundamental issue that an asynchronous event-loop model and a synchronous batch model are just different programming paradigms to begin with. |
|
Some statically typed languages (I believe both Haskell, ocaml) have powerful type system that allow abstracting over function types and function colors. Color is not an issue here.
Some other statically typed languages (C#, rust, and C++ (at least with the built-in stackless coroutines)) can abstract over types but not over colors. This is a problem.
Some statically typed languages (Go) do not encode async-ness statically, so it is not an issue[2].
Some dynamically typed languages (scheme, Lua, lisp) also do not encode async-ness statically. Everything is fine.
Finally there are some dynamically typed languages (python, js) that, eskew static types but for some reason still decide to encode async-ness statically. For me this is the most bizarre decision, especially as some of the justifications for static async-ness (performance, memory usage) are less relevant.
[1] for example, a litmus test is being able to implement an higher order function that inherits its color from one of its parameters. Essentially this is the problem of generically turning an internal iterator to an external one.
[2] fundamentally in these languages continuations are first class values that can be passed around, so the asyncness is naturally not bound to the function that created a continuation.
Edit: you can in principle abstract away color in any async language by simply assuming that any function call is async and await it. Then sync functions can trivially be made async. But at this point async annotations no longer convey any useful property: the language might as well implicitly await any function and require call-site annotations for diverging control flow or reentrancy requirements. More practically as languages with async evolve and grow asyncness becomes pervasive and pushes away any sync component.