From C++ to Erlang
As a game developer, I used to work on the client-side of games, especially low-level engine programming, graphics/rendering and animation, mostly with C++. More than a decade of coding in C++. Through some unexpected turns of events and due to my interest in functional programming languages in general, I recently moved into a team working on game’s chat system in Erlang. My favorite is Haskell when it comes to functional languages, but there was no team using it at my current employer.
It was a big change, not just in the language, but also in development environment (from Windows to Mac) and tech stack (from developing applications to run on players’ machine to creating back-end software for distributed nodes). Now it’s been about four months since the switch and I have now become more or less familiar with the language itself and associated tech stack for distributed computing like AWS, Terraform and others we’ve been using (to a lesser degree). I also been to Erlang Factory SF 2016 last March, which was a good opportunity to feel the vibe of Erlang community. Here I’d like to share my personal and subjective impressions on the language so far.
Erlang is a dynamically typed functional languages with its own virtual machine, well-suited for concurrent and fault-tolerant systems. It started as a language (and associated middleware/libraries called OTP, which represents for Open Telecom Platform) for telephony systems. You can see why Erlang can be adept at distribution and fault-tolerance from its origin.
The language was originally implemented in Prolog and its influence still remains in its rather strange syntax (especially to programmers from C-style languages). ‘,’ is used to separate a sequence of statements (‘.’ designates the end of the sequence) and ‘;’ represents each case of pattern matching (further discussed below). The comma also can mean logical AND, and the semicolon can act as logical OR. One of the weirdest things is its less-than comparison operator, which is ‘=<’ rather than ‘<=’. Admittedly, all these don’t really matter once you get used to the language.
Another thing I found peculiar at first was its atom type. You can think of it as run-time managed hashed string literals. It’s versatile and you can use it as any of enum, error code, variant tag, or whatnot.
Loads of processes
Erlang’s advantage for concurrency and distribution comes mainly from its lightweight processes and message passing, based on Actor model or CSP. It took some time for me to acquaint myself with thinking in terms of multiple processes communicating with each other through message queues, when designing a program. Another interesting approach coming from this is its Let It Crash philosophy. Instead of trying to prevent all potential crashes (even ones very rarely happening in production) from ever happening, it says just let the offending process crash and restart it from scratch (as long as it doesn’t adversely affect other running processes.) Erlang/OTP supports such a crash-then-restart strategy through supervision trees and process monitoring/linking. As a programmer mainly worked in native/low-level languages, where any crash is a big no-no, this approach is still quite alien to me, to be honest. I can see its point, though. No software (or hardware for that matter) will be entirely perfect (bug-free) and sometimes it can make more sense (and cost-effective) to make the system more tolerant to such rare crashes rather than trying to make it 100% crash(or bug)-free.
Immutability and pattern matching
Variables in Erlang are not your usual variables. You cannot reassign them because they are immutable. The initial assignment to a variable is thus called binding. Once bound, its value cannot be changed. It’s beneficial to check a flow of data and where modification happens. But I notes that I often need to come up with a sequence of variable names like State, State2, State3 to circumvent the limitation, even when I’m certain the ‘State’ won’t change from the specific chain of calls, where each call gets the ‘State’ as an input and returns a potentially modified ‘State’ (Apparently someone made a solution for this by using parse transform, Erlang’s metaprogramming facility. Not sure if the situation warrants such a heavy-duty solution, though.)
Pattern matching is another feature you’d better get used to. It would be an unfamiliar thing to C++ programmers (C++ templates have a sort of pattern matching behavior and there has been an attempt to add the feature to the language, though.) Let’s look at some examples:
My old habit as a C++ programmer makes me to write a code like:
But, it’s more erlang-ly to use the pattern matching like:
First of all, getting the length of a list is O(n), which is not really necessary in this code. Pattern matching provides more efficient and arguably more readable implementation.
As someone who prefers static typing, especially a powerful one like one provided by Haskell, Erlang’s dynamic typing is a pet peeve of mine, to say the least. To prevent some silly (but deadly) mistakes coming from the lack of type checking, Erlang supports a type checking based on annotations and something called success typing. It’s not perfect and sometimes gives you inscrutable error messages, like the ones you can encounter while doing C++ template metaprogramming. Nevertheless it helps in many cases and my team has been actively using it.
A new kid on the block, Elixir
As I noted, Erlang is a vm-based language, which means there can be other languages running on the same virtual machine. LFE (List-Flavored Erlang) and Elixir are good examples. The latter is gaining traction recently among Ruby developers. It’s boasting Ruby-like syntax and a powerful macro system and positioning itself as a Ruby(and Ruby-On-Rails) alternative.
Users and community
So, who the hell are actually using this obscure language in production, you might ask. There are a few, some of which you may even be quite familiar with. WhatsApp, a popularmobile messenger app (now owned by Facebook), is using it. Facebook messenger was also based on Erlang originally, although it has been switched to C++ a few years ago. Given its origin, Erlang is a natural fit to such messenger systems. Riak, a NoSQL database, is based on Erlang, too. An open-source message broker software, RabbitMQ, is another. Some game companies are using Erlang for its back-end servers. Even some purely client-side applications (e.g. http://www.wings3d.com/, a 3D modeler software) has been written in Erlang.
The conference I attended, held for two days in San Francisco, was small (if I compare it to something like, you know, Game Developers Conference or SIGGRAPH), around 250 attendance this time, I think. The community seems friendly and inviting, though. It was easy to have a chitchat with a guy who created the language, for instance. Multiple sessions there were quite inspiring, too.
I hope this write pique your interest in the language, especially if you’re working on a distributed system. As a language geek, I think it’s worth studying Erlang even though you’re not going to use it in production. It has some interesting concepts and approaches, which you can still apply in other languages.
Resources for learning Erlang
- Learn X in Y minutes (where X = Erlang): https://learnxinyminutes.com/docs/erlang/
- How I Start (with Erlang): https://howistart.org/posts/erlang/1
- A nice introductory presentation on Erlang: http://ferd.ca/the-zen-of-erlang.html
- A book, “Learn You Some Erlang” (its online version freely available): http://learnyousomeerlang.com/content
- An ebook by the same author on not-so-beginner stuff like devops and profiling: http://www.erlang-in-anger.com/