Hoare’s billion dollar idea

Folks, I propose that we forgive Tony Hoare for his billion dollar mistake. Yes, he invented null, and of course all the trouble that got us in is his fault. Fortunately, he also invented CSP, one of the many formalisms for dealing with multiple things happening at the same time. I believe that CSP may end up being his multi-billion dollar idea, more than repaying his null debt to society.

Complicated Scientific Papers

In the time when Hoare invented CSP (1978), every CS professor came up with his own formal language for roughly the same thing. CSP however, has two particularly fantastic features that separate it from the crowd.

First of all, while CSP itself is pretty theoretical and fundamental in nature, most people combine the CSP primitives to roughly the same higher-level building blocks, and these are pretty easy to understand. Secondly, and most importantly, these building blocks are actually in programming languages! Sure, it took us programmers more than 35 years to figure it out (okok except Joe Armstrong, who did it in 8), but still, it’s there!

I’m talking, of course, about channels and processes like they exist in Go, Erlang, Clojure (core.async) and a bunch of other languages. Nitpickers will immediately complain that Erlang doesn’t really have channels because it follows the Actor model instead, but you can simulate channels with actors and you can simulate actors with channels, so I’m going to completely gloss over that difference from here onwards. The most important part are processes and we have those in all these languages.

Processes are awesome!

The idea of a process is a piece of code that actively does something and occasionally tells others about it. It looks and feels a bit like a thread, except that you don’t have to think about how much a resource hog threads can be. Also, because you’re not supposed to use shared data, you don’t have to think about mutexes and all that other stuff either. You use messages for sharing data.

For example, in a UI application, you could have a process that polls for mouse click events. “Wait”, I hear you say, “don’t mouse clicks usually come from some sort of event loop? Why poll?”. Indeed they do, but the fun about processes is that you don’t really care about that. Even if in some weird UI system, you’d need to actively poll for mouse clicks, you can make the process work exactly the same from the outside.

This mouse-click-poller process could report clicks, with some additional event information, on a channel, and any other process that is interested in mouse clicks and receive messages on that channel. This feels a bit like normal event listening, but the fun is that the mouse-click-poller can also do some other processing on the event. Maybe make the event object easier to consume for listeners, do some post-processing or cleanup work, and the listeners don’t need to change how they work at all.

This is fantastic separation of concerns, and allows for excellent composability. You could have a process that listens on channels of mouseup, mousedown and mousemove events and produces drag events on another channel, for instance.

Cute little robots with opinions

Many other programming languages allow you to do similar things. For example, C# gave birth to the excellent Rx library and has fancy language-level async/await support which allow you do so a similar thing. In fact, composing multiple lower level mouse events into drag events is sort of the “Hello World” of Rx. As another example, you can’t call yourself a competent JavaScript developer these days without embracing promises or streams something comparable. These are all great tools for dealing with asynchronicity and concurrency, but I feel like they all, at least in some ways, make a program more complex to understand. I want my program to be simpler.

Being able to treat everything that has some sort of active behavior to it as a separate process is a truly liberating experience. I first had it when learning Elixir, a language based on Erlang, in which such processes are a native feature. Many programmers had it when learning Go and writing their first goroutine. I find that “behavior”, as vague a concept as it is, is a much more important thing than “asynchronicity”. Therefore, I believe that is not the right solution to add language level support for things like “async methods” (C#) or “async return values” (JavaScript promises, Scala futures, etc). As a caller of functions, I shouldn’t really care whether something is async or not, I should care whether I’m interfacing with this independent, active thing over there (like a cute little robot with an opinion) or a simple function that turns some input into some output (like the calculator on my desk) (okok the calc.exe in my Run dialog). Cute little robot? Process. Calculator? Function.

The world’s most popular programming language

You can imagine my happy joy when I finally got around to reading James Long’s excellent blog post on putting CSP processes in JavaScript. If you do any frontend coding, do yourself the favor of at least skimming through his post. To me, this style of programming feels so much better and cleaner than promises or callbacks or all that mess, that I can hardly fathom it. Fair enough, it requires ES6 generators, which in turn require either hyper-modern browsers, or a Node.js fork built by irresponsible hippies, or compilers like Regenerator which produce horrible JavaScript. But hey, we have source maps anyway, so who cares about what the browser sees?

I truly believe that the future of anything that has asynchronous or concurrent behavior, which is nearly any piece of performant software really, lies in the concept of CSP-like processes. Processes are to futures, tasks, async/await, and promises what garbage collection is to malloc() and free(). The latter burden the programmer with, in my eyes, unnecessary implementation details in the vast majority of cases. I want to organize my program into a number of cute little robots, not into a big bag of functions that may or may not have asynchronous behavior and oops you forgot to catch() that promise and what the hell just happened in which order again?

Processes are the future, futures are not, and it is now.

I am going to use JS-CSP in all my future frontend projects. I’m going to avoid languages on the backend that don’t either natively have processes or have a great library that supports it. Dear C#, I truly love you, but you’re out the door for me until you get your concurrent act together. Processes are great, all the other stuff is not, and I have CSP to thank for it.

Is CSP going to be Tony Hoare’s billion dollar idea? I think that maybe it already is.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s