UP | HOME

Erlang

It is hard to tell, especially to an uninitiated, that Erlang is a both a minimalist and principle-based language - a set of necessary and sufficient features which are orthogonal but complementing to each other.

CLU, Scheme, Standard ML and Haskell are other such languages.

Some syntactic oddities are the primary cause of why people give up too early. Syntax aside, it is otherwise brilliant. The designers has a solid mathematical background and it can be seen.

Unlike SML, Erlang has heterogeneous lists and type-tagged values, just like Common Lisp or Scheme.

Just like Haskell and lately Python, Erlang has purely declarative list comprehensions, which can be traced back to the mathematical notation, developed within the Set Theory (the basis for all mathematics).

Being declarative with a high-level DSL is the highest possible level of excellence. Besides set comprehensions, summations and integrals are examples of such declarative notations.

We, in programming, use DSLs, sometimes as beautiful and close to math as Scala’s scalatest set of libraries or the original quickcheck for Haskell.

Erlang lacks some abilities of expressing DSLs due to neglect of syntax. Currying and partial application + the ability to define arbitrary infix operators is what it is lacking.

User-facing subset of Erlang is pure functional. send is an infix operator and acts like an identity function. recieve is like a multi-clause “function” (it is pure with respect to the pattern and a given context).

spawn is a pure as apply.

Just like SML, pattern-matching is the main mechanism of dealing with structured and nested values.

Erlang pioneered universal pattern-matching (first introduced in SML), which means patterns are everywhere.

= is not an “assignment”, but binds unbound symbols or is an “assertion” for both sides of = to have the same shape with exactly the same values. SML uses let.

Patterns could appear in list comprehensions for both descructuring and constructing.

Function clauses (which SML also have) also defined by pattern-matching. Thus each clause becomes a partial function (defined only on a particular subset of the domain).

Functions with more that one clause are usually defined for algebraic sum-types, and the overall shape of a function follows to the shape of a data-type.

Unlike SML, Erlang does not support currying and partial application.

Pattern-matching on receive is Erlang’s unique innovation. This allows to examine the shape of received data, destructure and bind to symbols.

Each receive clause is a partial “function” with “arguments” being bound by the pattern-matching process.

the [H|T] syntax. In a pattern it unpacks and binds, in an expression it constructs.

We can easily add tests and perform test-driven development without any additional tools. All we need is /pattern matching and =.

result (self-evaluating) = expression

this is an implicit assertion about structured values (of the same shape).

Don’t handle the case where no pattern matches—our program will fail with a runtime error. /This is deliberate. This is the way we program in Erlang. (Fail fast!)

tuples

The idea is to add an atom as a tag as the first element of a tuple and pattern-match against such tuples is simply brilliant and just right - it is rational, /principle-guided minimalism.

when guards

These are just expressions of the type true | false (those are just atoms).

  • , is an implicit strict AND, because all the expressions are going to be evaluated in order.
  • ; is an implicit strict OR, because the later will be evaluated (in order) when the former fails.
  • andalso and orelse are short-circuiting logical operators (evaluation stops on the first false or true respectively and the second expression will not be evaluated).

Notice how , is is the essence of product-type and ; in this context is just | of a sum-type.

test(X) when X =:= cat; X =:= dog -> yay % either cat or a dog

The set of standard predicates is a reminiscence of Common Lisp ones, just with a different naming convention – is_something(x).

Let it crash. Fail Fast and Noisily. Crash, Crash, Crash.

The proper way is to expect an “error” in a sum-type of a return value.. Erlang’s way is to return a tuple with {ok, Value} or {error What}. Another way is to throw an exception.

The most important thing is that errors has to be well-understood and expected.

Fault-tolerance requires a supervision hierarchy (redundancy). A supervisor must “know what to do” (usually just restart).

Author: <schiptsov@gmail.com>

Email: lngnmn2@yahoo.com

Created: 2023-08-08 Tue 18:31

Emacs 29.1.50 (Org mode 9.7-pre)