4 ms·
Can you illustrate how/why the abstraction is broken?
by monadic2 6y ago
Can you illustrate how/why the abstraction is broken?
- jonahbenton 6y agoWell, as with all conceptual discussions, clarity, receptivity and sufficiency are a function both of speaker and of audience. The variations in both produce a multiplicity of arguments, and googling for why async/await suck will lead to rich troves to explore. I can't reproduce the spectrum in anywhere near finite time. But I'll go with the two most cogent for me. The first and most important is that Python made its bones with an enforced single thread execution runtime- with the GIL- that dramatically simplified the mental machinery a programmer needed to do productive things with computers. Extremely successful approach. Async/await, as keywords- core parts of the language- are a complete conceptual departure. Like Python was a very safe multipurpose Swiss Army knife, that now as part of the core has a powersaw. For people who need the powersaw capability, with the ergonomics of a simple blade, Python has always had libraries and module extensibility, and the brilliance of the dunder methods that give access to the machinery for experts who need it. Clear distinction between 95% and 5% use case tooling. Second, as concurrency-enabling abstractions, async/await are poor because they are an opinion that what is hard about concurrency is code. This is a bad opinion. It is data that is hard. When you are dealing with things happening in parallel, trying to understand them, you realize that the understanding part is only hard when there are dependencies between the parallel things. In computing terms, those dependencies are expressed with data relationships. One process waits for another only because it needs some data from it, or it needs it to be ready to receive some data. Things that don't share data, in one form or another, do not care about each other. Queues- a data structure- help model data dependencies explicitly. Async/await only model them implicitly, and poorly, at that. For every await, there is a use case for a queue that much more clearly and composably expresses the true dependency between the potentially concurrent operations. Async/await- as conceptual flags for code blocks- are helpful optimizations for experts, where the operational ergonomics of interacting concurrent processes are well known enough. And for experts they help unify two different concurrency domains- processor-based being one, io-based being the other. This is why you see examples of use of these in state machines and ioloops, both expert level optimization constructs. But even there, they are attributes of a code block, something that should be reachable through some dunder-token, as are other expert level machinery/magic. To add them as top level standalone keywords in a language lauded for being executable pseudocode is an astonishing misunderstanding. Hope that is helpful. Again, CSP is a much more approachable mental model. A Golang-like channel construct would have been a much better addition to the language in place of await. And exposing a not-directly-executable dunder flag much better than async. Cheers.