5 ms·
We do not want red and blue functions. Any language that implements async / await as coroutines instead of green threads is making a fundamental CS mistake. ht
by divyekapoor 3y ago
We do not want red and blue functions. Any language that implements async / await as coroutines instead of green threads is making a fundamental CS mistake.
https://journal.stuffwithstuff.com/2015/02/01/what-color-is-your-function/ https://journal.stuffwithstuff.com/2015/02/01/what-color-is-...
Concurrency's correct primitive is Hoare's Communicating Sequential Processes mapped onto green threads. Some languages that have it right are Java (since JDK17 - Java Virtual Threads), Go, Kotlin.
- pornel 3y agoThis classic article mixes two things: 1. inability to read an async result from a sync function, which is a legitimately major architectural limitation. 2. author's opinion how function syntax should look like (fully implicit, hiding how the functions are run). And from this there is the endless confusion and drama. The problem 1 is mostly limited to JS. Languages that have threads can "change colour" of their functions at will, so they don't suffer from the dramatic problem described in the article. But people see languages don't fit the opinion 2, of having magic implicit syntax, and treat it as an equally big deal the dead-end problem 1. But two syntaxes are somewhere between minor inconvenience to actual feature. In systems programming it's very important which type of locks you use, so you really need to know what runs async.
- kasdi 3y agoMaybe the issue is that we overload the concept of a function with an entirely different thing, a Future / Promise. Maybe if the syntax would have been entirely different too, it would have been easier to understand. We tend to have different syntax for different things. I’m hesitant towards not distinguishing different things anymore and let the underlying system “figure it out”. I’m sure this could work as long as you’re on the happy path, but that’s not the only path there is.
- jeroenhd 3y agoVirtual threading is fun and all until you find out SimpleDateFormat and a bunch of other classes built tight into your standard library aren't thread safe and now you need to go through your program and find out what else you missed. Go too has these fancy green threads at the cost of manually locking resources and finding out about race conditions when you forget about them. Futures aren't a fundamental CS mistake, they're a design decision. You may disagree with that decision, but the advantage Rust brings is that you don't need to worry about thread safety once your program actually compiles, at the cost of different code styles. Neither asynchronous processing design is fundamentally wrong, they both have their strengths and weaknesses.
- SpaghettiCthulu 3y ago> Virtual threading is fun and all until you find out SimpleDateFormat and a bunch of other classes built tight into your standard library aren't thread safe and now you need to go through your program and find out what else you missed. Go too has these fancy green threads at the cost of manually locking resources and finding out about race conditions when you forget about them. Why would that ever be an issue? Instances of those classes shouldn't be shared between virtual threads just the same as when using regular threads.
- peoplefromibiza 3y ago> until you find out SimpleDateFormat and a bunch of other classes built tight into your standard library aren't thread safe true, but DateTimeFormatter has been available since Java 8, released almost 10 years ago. VirtualThreads will be available in Java tomorrow Also: https://docs.oracle.com/javase/8/docs/api/java/text/SimpleDateFormat.html#synchronization https://docs.oracle.com/javase/8/docs/api/java/text/SimpleDa...
- omnicognate 3y agoAlways with the blooming red and blue functions. You can say exactly the same thing about const. The fact that a function can perform asynchronous operations matters to me and I want it reflected in the type system. I want to design my system on such a way that the asynchronous parts are kept where they belong, and I want the type system's help in doing that. "May perform asynchronous operations" is a property a calling function inherits from its callee and it is correctly modelled as such. I don't want to call functions that I don't know this about. Now you can make an argument that you don't want to design your code this way and that's great if you have another way to think about it all that leads to code that can be maintained and reasoned about equally well (or more so). But calling the classes of functions red and blue and pretending the distinction has no more meaning than that is not such an argument. It's empty nonsense. "We" don't all agree on this.
- randyrand 3y agoMaybe a better example is returning errors, than const. Either way, all of these changes are really annoying to make. We want less of these annoyances, not more.
- assbuttbuttass 3y ago> The fact that a function can perform asynchronous operations matters to me and I want it reflected in the type system. async doesn't tell you whether the function performs asynchronous operations, despite the name. async is an implementation detail about how the function must be invoked. As TFA correctly points out, there's nothing stopping you from calling a blocking function inside a future, and blocking the whole runtime thread.
- omnicognate 3y agoI didn't say it tells me whether the function does perform such operations, I said it tells me it can. More importantly it tells me which functions (most) can't.
- anonymoushn 3y agoIt would be swell if functions could be generic over this capability at compile time, so that you could get the same guarantees from the type system without implementing the same protocols more than one time.
- vilunov 3y agoI want colored functions. I want to know which code is running synchronously and which doesn't, which raises errors and which doesn't. Color is just a description of the function's properties (and effects) and how it's compatible with other colors. There is also nothing fundamentally bad with cooperative scheduling in scope of a single process.
- jerf 3y agoI got into programming in the 1990s. At that point in time, there was still a large contingent of programmers loudly insisting they needed assembly language to do everything. And to be clear, I mean, everything. Not "Yeah, I can't really bring up an OS without a bit of specialized assembly" but "every programmer should write every program in assembly". The vast majority of them were already wrong. They only got more wrong. You may just be used to knowing what code is "synchronous" and what isn't because it's been shoved into your face and you've adapted your thought process to it. In practice, "everything important is doing something 'asynchronously'" turns out to be the vast majority of what you need, and the vast majority of your mental energy you are dedicated to splitting the world in two is a waste. For the little bit that remains, by all means use something specialized, but it's just not something that everyone, everywhere, needs to be doing all the time, any more than everyone everywhere should be manually allocating registers, or any more than programs need to have line numbers because otherwise how can they work? (One of my favorites because I remember having that conception myself.)
- the_af 3y agoI think you have your analogy backwards: the "assembly programmer" in this situation is the person who doesn't understand why one would "color" functions and/or express a fundamental property as part of their types. "Why do we need to express this in their type? Every programmer should be able to understand this without help".
- dgb23 3y agoTo me this kind of sounds like circular reasoning. Without function coloring there's no distinction that you need to know of. Can you elaborate?
- NSufi 3y agoI think with stackful coroutines you lose low-overhead interoperability with C. Also, it possible to use stackless coroutines without introducing async/await 'colors'.