Rust's async isn't colored!

EDIT:

Since the blog post has gained quite a bit more traction and discussion than I thought (/r/rust HN), I think it's important to explain one grave mistake I've made in this blog post: When writing it, in my head I used "suffers from the coloring problem" and "is colored" interchangeably, but obviously there is a difference between the two. Needing to refer to async and sync functions as seperate things clearly shows that there is some color to them. The article should probably instead be named "Rust's async fns are colored, but I don't think that's a big problem, and here is why" (or a more catchy version of that). The article was very rushed (since I usually spend too much time on them and few people end up reading them), so the language is not as precise at it should have been. I'll see if I can soon write a follow up that also addresses some of the interesting points I've read in the comment sections.

EDIT2:

I've decided against writing a follow-up post, as someone has written a great blog post "Rust async is colored, and that’s not a big deal" that captures the topic (and my thoughts on it) very well. Go read it!


For some time now, I've had a love-hate-relationship with the famous blog post What Color is Your Function?.

One the one hand it's a great article that hits the nail on the head why using async/await in JS (and other languages) is very painful, and it provides us with the great allegory of "colored functions".

On the other hand, since the article has become widely known, people use the argument of colored functions to shit on every implementation of async/await, whether it applies or not. In particular it seems to be a recurring talking point that comes up in discussions of Rust's async/await even though - you might have guessed it - it doesn't apply!

So let's review the argument in the original post and see where it breaks down for Rust:

1. Every function has a color. βœ…

Sure, a Rust function either has the async keyword or it doesn't.

2. The way you call a function depends on its color. βœ…

I guess that's also true. You will generally call a normal function like foo(), and most of the time you will call an async function like bar().await.

3. You can only call a red function from within another red function. ❌

This is most important point, and also where it breaks down!

Colored functions are problematic because they turn everything you touch into the same color as well. Want to color a function in your colored programming language? Have fun turning every function that calls it (and that calls them, and so on) the same color!

However this is not a problem in Rust! In Rust, you can easily confine the coloring to exactly the part of the code you want to, and doing it is pretty straightforward:

Want to call an async function blockingly from a sync function? -> Throw it on an executor!

Want to call a sync function from an async function? -> Either just call in normally, or if it would block your async function spawn it as a blocking task! async-std variant, tokio variant, and I'm sure your async runtime of choice has something similar.

Of course you shouldn't do both of those things all the time, or you will lose most of the benefits of using async in the first place! However sometimes you don't really have a choice, and this super cool crate you want to use is async or sync (obviously always the version you don't need right now), and you have to make it work.

async/await in Rust let's you decide how much/little of your code you want to color!

4. Red functions are more painful to call. βœ…/❌

Kind of? In traditional Rust fashion, I wouldn't really call it painful, but more verbose. It's one of the typical downsides of being explicit and giving the developer full control. I personally don't mind it much, as that explicitness is one of my favourite things about Rust.

5. Some core library functions are red. ❌

As of the time of this writing, there is no async function in the standard library in Rust that would force you to color any part of your code. However, depending on the crate ecosystem you want to use, large parts of it might lean towards async (though usually for good reason).


So there we have it: Rust's async isn't colored!

If you want to complain about Rust, there are plenty of other things to choose from, even other parts of async/await, but async coloring is not one of them.