Live data from Hacker News

What color is your function? (2015)

journal.stuffwithstuff.com

21–30 of 198 posts

Re: What color is your function? (2015)

#21

Earlier quoted context omitted.

For Python backends I've seen good success with just making it company policy that everything is synchronous (normal-colored) and bypassing the developer overhead from async/await. Cooperative multitasking is a pain because, well, it requires cooperation. You can go pretty far by just adding more threads, processes, and replicas before it's worth the overhead.

You not only leave performance on the table (which depending on your use case/environment, may not matter if you can just throw more threads at it) but also some developer ergonomics. asyncio.gather is a lot less code than having to manage a thread pool or something like Celery with all it's underlying infrastructure. If you're in an ecosystem where a lot of the async boilerplate is free/cheap (ex: FastAPI) then the…

> something like Celery with all it's underlying infrastructure.

Unpopular opinion, but combining this with the other "no thanks" sentiments in this subthread is the right answer. Your app is so complicated you need async? Then it's complicated enough that you can benefit from infrastructure. I don't want to watch coworkers try to badly rebuild message queue or scheduling semantics in an application code base. Just use infrastructure that's made by people who know what they are doing. That was problematic in 2015, but in 2026 it's a bit of docker, and it's not just about web/microservices. Very easy for sufficiently complex apps to simply leverage a local sandbox of celery, redis, graphdb's and whatever. Stand-alone is overrated since we don't have to do it anymore.. app devs should get more comfortable working with ensembles like this so they have access to best-in-class solutions.

You don't like infrastructure AND have such a need for performance AND don't want threads or multiprocess? Consider using another language. Async is mostly a solution in search of a problem, and the enduring popularity of TFA goes to show this has been the right conclusion for ~10 years.

Re: What color is your function? (2015)

#22

Earlier quoted context omitted.

You not only leave performance on the table (which depending on your use case/environment, may not matter if you can just throw more threads at it) but also some developer ergonomics. asyncio.gather is a lot less code than having to manage a thread pool or something like Celery with all it's underlying infrastructure. If you're in an ecosystem where a lot of the async boilerplate is free/cheap (ex: FastAPI) then the…

Performance aside (which I would argue is premature optimization, as most programs will not feel the theoretical overhead of threads), async is a bad approach for developer ergonomics. Threads are so much easier to work with and reason about than async. There are reasons to use async (like if you're in the rare case when thread overhead is noticeable), but developer ergonomics are absolutely not a reason.

Say I need the results from two expensive REST API calls, so I want to run them concurrently. Managing a thread pool you find a _better_ experience than

one, two = await asyncio.gather(callOne(), callTwo())

?

Re: What color is your function? (2015)

#23
post #16

Colored functions are good. It reflects the language design on signaling what is important, and what are the properties it want the writer to pay attention. Other examples of colored functions: * Haskell: pure function and non-pure (IO monads) looks different. * Rust: unsafe functions (or block) requires special markers.

My mind went to Java's checked exceptions -- not sure if anyone today believes that coloring is still a good idea.

Re: What color is your function? (2015)

#24
post #6

> You still can’t call a function that returns a future from synchronous code. (Well, you can, but if you do, the person who later maintains your code will invent a time machine, travel back in time to the moment that you did this and stab you in the face with a #2 pencil.) Author makes up a lie. Then lampshades it away with a colorful non sequitur. --- The alternatives that people praise like golang, have other trad…

Your entire codebase is already at risk of being blocked by a spinlock or CPU-intensive operation, so what's the difference?

Re: What color is your function? (2015)

#25
post #10

I wish the key word was instead dontawait and was used inversely to how await is used. 99% of the time I'm using an async function, despite however slow it is, there's nothing for my code to do but wait for it to finish. But if for some reason I would like the next line of code to run before the current one is done, I'll let you know . Like, why can't my sync function await something asynchronous? If it has to lock u…

> Like, why can't my sync function await something asynchronous? The answer, at least for Python, is that it is an intentional limitation because the alternatives introduce some quite bad trade-offs. Option 1: your awaited promise goes into the main async event loop. This is bad because it means that your single-threaded sync function now needs to be thread-safe, and so does any sync code that calls your sync functio…

I think the downsides of option 2 are overstated here. In lots of cases you don't care about the "value of async", you just want code that works well enough and option 2 does accomplish that in anything that is not perf critical.

Re: What color is your function? (2015)

#26

We need algebraic effects in more languages, this solves the function coloring problem. OCaml 5 has them and it seems to be doing quite well, combine that with the semantics of the borrow checker in the form of OxCaml and we might just have an ideal language. I'd like to see algebraic effects in Rust as well but sadly it seems their keyword generics initiative is languishing. Related, one of the former React maintain…

I don't think effects alone solve function coloring problem, in worst case they make it worse because every library can have its own colors

Re: What color is your function? (2015)

#27
post #16

Colored functions are good. It reflects the language design on signaling what is important, and what are the properties it want the writer to pay attention. Other examples of colored functions: * Haskell: pure function and non-pure (IO monads) looks different. * Rust: unsafe functions (or block) requires special markers.

My mind went to Java's checked exceptions -- not sure if anyone today believes that coloring is still a good idea.

The problem with checked exceptions afaik was far more in the execution than in the idea itself. And also late 90s-early 00s was different time in general.

Re: What color is your function? (2015)

#28

Earlier quoted context omitted.

You not only leave performance on the table (which depending on your use case/environment, may not matter if you can just throw more threads at it) but also some developer ergonomics. asyncio.gather is a lot less code than having to manage a thread pool or something like Celery with all it's underlying infrastructure. If you're in an ecosystem where a lot of the async boilerplate is free/cheap (ex: FastAPI) then the…

> something like Celery with all it's underlying infrastructure. Unpopular opinion, but combining this with the other "no thanks" sentiments in this subthread is the right answer. Your app is so complicated you need async? Then it's complicated enough that you can benefit from infrastructure. I don't want to watch coworkers try to badly rebuild message queue or scheduling semantics in an application code base. Just u…

I said nothing about "stand-alone" services. I'm all about using the right solution to the problem. We run on Kubernetes and have access to message queues. But if all I want to do is make a couple of HTTP calls concurrently, I don't think I should have to manage a thread/process pool to do so, or lean on a message queue or redis based RPC mechanism. In an async context I can do this with a single line of code.

Every rich client-side experience in your browser is written using async code in Javascript or Typescript, as is every electron app. Every developer at my company is comfortable with this pattern, and frameworks like FastAPI make this a similarly smooth experience when using Python.

If async was a solution in search of a problem, it wouldn't have been stolen from C# and added to Rust, Python, Kotlin, etc. The engineering effort required to bring this solution to all these languages is immense, so I'm clearly not the only person seeing value in it.

Re: What color is your function? (2015)

#29
post #3

Go doesn't have colored functions due to its nice fat runtime hiding all the async magic away for us. That makes it a pleasure to code concurrent stuff for IMHO. It does have its own similar problems though - does a function return an error? If so you are going to need to plumb the error return through all the callers. Does a function need a context.Context? Ditto. I guess you can't win them all :-)

Same with the BEAM languages like Erlang, Elixir, and Gleam. Though it still bothers me that they call their green threads "processes".

That's mostly because BEAM uses an actor-style approach while predating the concept of actors, isn't it? Interesting artefact of history if so

Edit: upon rechecking, apparently that's not exactly right, and Erlang designers learned of actors after designing the language, which makes it all the more interesting

Re: What color is your function? (2015)

#30
I really don't like this article. It has a catchy, profound-sounding title that people bandy about to argue against stuff they don't like.

All functions, even non-async functions, are colored. In any large system codebase you'll have functions that can only be called in certain situations, with the right setup, whatever, and if you're lucky this is communicated by types but regardless those restrictions can't be avoided. It's easy to call low-restriction functions from high-restriction ones and not the other way around.

Furthermore, it's not like the alternative to explicit await doesn't have issues too (that the article doesn't mention). There is inherent complexity, it's a tradeoff, you can't just syntax it away.

Post reply on HN