Saturday, February 6, 2016

Erlang: The equals sign is a matching operator

In all previous programming languages I have used before Erlang, the equals sign means assignment. When you see
X = 1;
this reads as "assign the value 1 (one) to X."

Erlang is different. In Erlang, you read this like a mathematical statement: "find the value of x that makes the left-hand side of the equation equal to the right-hand side."

This simple difference in the meaning of = quickly gets more useful. For example, consider this:

"/" ++ Path = HttpRequest:get(path).

In Erlang, this says "find the value of Path that makes this statement true". This is nearly equivalent to the following Java code:

String Path = HttpRequest.getPathInfo().substring[1:];

I say nearly equivalent, because there is something else going on in the Erlang statement. The Erlang equals sign is stating that the equality holds, so a more precise Java translation is:

String Path;
if (HttpRequest.getPathInfo().startsWith("/")) {
   Path = HttpRequest.getPathInfo().substring[1:];
} else {
   String emsg = "no match of right hand side value \"%s \"";
   throw new IllegalStateException(emsg.format(HttpRequest.getPathInfo());
}

That one line of Erlang both asserts a pre-condition and binds a variable to a value.

This technique works in function arguments:

$ cat t.erl
-module(t).
-export([test/1]).

test("/" ++ X) -> X.
$ erl
1> c(t).
{ok,t}
2> t:test("abc").
** exception error: no function clause matching t:test("abc") (t.erl, line 4)
3> t:test("/abc").
"abc"
4>

And for other types:

4> [{X,Y}] = [{1,2}, {2,3}].
** exception error: no match of right hand side value [{1,2},{2,3}]
5> [{X,Y}] = [{1,2}].       
[{1,2}]
6> 

What I am finding as I code more in Erlang is that I now code only the happy path. This is a fun way to write code! I like to write safe code, but having to catch and handle all the error cases sucks the fun out of it. With Erlang, I get both: I write the happy path and I get pre-condition assertions built-in.

And going back to the first example, what are you going to do in a Java Servlet running in a container so buggy that the CGI PATH_INFO variable is missing it's leading slash? Crashing and then restarting the Servlet seems like a reasonable action. That's exactly what Erlang does by combining pattern matching and Supervisor behaviors.