Remix.run Logo
the_mitsuhiko 6 days ago

> There is an implied assumption that async/await is a "functional feature" that was pushed into a bunch of innocent imperative languages and polluted them. But there is one giant problem with this assumption: async/await is not a functional feature. If anything, it's the epitome of an imperative flow-control feature.

async/await comes from C# and C# got this as an "appoximation" of what was possible with F#. You can go back to 2011 where there are a series of videos on Channel 9 by Anders Hejlsberg where he goes into that.

That said, I don't think my post relies on the premise that this is a fight about imperative to functional programming. If anything the core premise is that there is value in being able to yield anywhere, and not just at await points.

> If you look at all of these use cases, you'd see all of these languages seem to have made the right pragmatic choice.

Potentially, who am I to judge. However that choice was made at a certain point in time and the consequences are here to stay. Other than in JavaScript where it's self evident that this is a great improvement over promise chaining (sans the challenge of unresolved promises), I'm not sure the benefits are all that evident in all languages. I do a fair amount of async programming in JavaScript, Python and Rust and the interplay between threads and async code is very complex and hard to understand, and a lot of the challenges on a day to day would really feel like they are better solved in the scheduler and virtual threads.

> Unless you are designing a new language from scratch (and that language is garbage collected and doesn't need to be compatible with another language or deal with a lot of existing native code), you can go with the ideological argument of "I want my function to be colorless" (or, inversely, you can go with the ideological argument of "I want all suspending functions to be marked explicitly"). In all other cases, pragmatism should win.

I will make the counter argument: even in some languages with async/await like Python, you could very pragmatically implement virtual threads. At the end of the day in Python for instance, async/await is already implemented on top of coroutines anyways. The "only" thing that this would require, is to come to terms with the idea that the event loop/reactor would have to move closer to the core of the language. I think on a long enough time horizon Python would actually start moving towards that, particularly now that the GIL is going and that the language is quite suffering from the complexities of having two entirely incompatible ecosystems in one place (two sets of future systems, two sets of synchronization directives, two independent ways to spawn real threads etc.).

ikekkdcjkfke 2 days ago | parent [-]

I always instantly await all my Tasks/promises. The only problem I have is that I have to type it out and wrap everything in Tasks. If the compiler would just automatically asyncify all the things that would be great, no need for green-threading or messing around with the engine, just hide the ugly details like you do with so many other things, dear compiler.