Sequential Erlang by Marcos Benevides

:ID: f0da3356-3797-4ddc-8306-cd333f159754

The basic constructs of the Erlang language.

Datatypes

Integers

If you need to do calculations on integers using a base other than 10, you can use Base#Value notation. (Laurent 2017, 7)

Floats

Atoms

Tuples

Tuples are created automatically when we declare them and are destroyed when they can no longer be used. Erlang uses a garbage collector to reclaim all unused memory, so we don’t have to worry about memory allocation. (Armstrong 2013, 35)

You can also pattern match tuples by using free variables:

  1> Point = {point, 10, 45}.
  {point,10,45}
  2> {point, X, Y} = Point.
  {point,10,45}
  3> X.
  10
  4> Y.
  45

Lists

  List = [ Element | List ] OR []

List Comprehensions

  1> L = [1,2,3,4,5,6,7].
  [1,2,3,4,5,6,7]
  2> [ 2*X || X <- L ].
  [2,4,6,8,10,12,14]
  3>

The most general form of a list comprehension is an expression of the following form: [X || Qualifier1, Qualifier2, ...], where X is an arbitrary expression, and each qualifier is either a generator, a bitstring generator, or a filter.

Strings

Strictly speaking, there are no strings in Erlang. To represent a string in Erlang, we can choose between representing the string as a list of integers or as a binary. When a string is represented as a list of integers, each element in the list represents a Unicode codepoint.

To print a unicode string one must use the “t” modifier applied to the “s” control character in a formatting string, it accepts all Unicode codepoints and expect binaries to be in UTF-8:

  1> X = "a\x{221e}b".
  [97,8734,98]
  2> io:format("~ts~n",[X]).
  a∞b
  ok

Records

(…) records provide a convenient way for associating a tag with each of the elements in a tuple. This allows us to refer to an element of a tuple by name and not by position. A pre-compiler takes the record definition and replaces it with the appropriate tuple reference. (Armstrong 2013)

  -record(todo, {status=reminder,who=joe,text}).

to load a record from the the shell, one must use the rr command:

  1> rr("records.hrl").
  [todo]
  2> #todo{}.
  #todo{status = reminder,who = joe,text = undefined}
  3> X1 = #todo{status=urgent, text="Fix errata in book"}.
  #todo{status = urgent,who = joe,text = "Fix errata in book"}
  4> X2 = X1#todo{status=done}.
  #todo{status = done,who = joe,text = "Fix errata in book"}

Maps

Maps are associative collections of key-value pairs.

  1> TaskPending = #{ status => pending, description => 'feed cats' }.
  #{status => pending,description => 'feed cats'}
  2> TaskDone = TaskPending#{ status := done }.
  #{status => done,description => 'feed cats'}

Identifiers

Pids

Ports

References

Variables

Note that Erlang variables start with uppercase characters. So, X, This, and A_long_name are all variables. Names beginning with lowercase letters—for example, monday or friday are not variables but are symbolic constants called atoms. (Armstrong 2013)

Pattern Matching

Pattern matching is used for:

case and if Expressions

  case Expression of
    Pattern1 [when Guard1] -> Expr_seq1;
    Pattern2 [when Guard2] -> Expr_seq2;
    ...
  end

  if
    Guard1 -> Expr_seq1;
    Guard2 -> Expr_seq2;
    ...
  end

Functions

Built-in Functions

List of BiFs

Funs: The Basic Unit of Abstraction

Funs are function closures. Funs are created by expressions of the form: fun(...) -> ... end.

Defining Your Own Control Abstractions

If we want additional control structures, we can make our own. Erlang has no for loop, so let’s make one:

  for(Max, Max, F) -> [F(Max)];
  for(I, Max, F) -> [F(I)|for(I+1, Max, F)].

Recursion

Tail Recursion

Guards

Modules

Defining Modules

    -module(drop).
    -export([fall_velocity/1, mps_to_mph/1, mps_to_kph/1]).

    fall_velocity(Distance) -> math:sqrt(2 * 9.8 * Distance).
    mps_to_mph(Mps) -> 2.23693629 * Mps.
    mps_to_kph(Mps) -> 3.6 * Mps.

Error Handling in Sequential Programs

  try FuncOrExpressionSeq of
    Pattern1 [when Guard1] -> Expressions1;
    Pattern2 [when Guard2] -> Expressions2;
    ...
  catch
    ExceptionType1: ExPattern1 [when ExGuard1] -> ExExpressions1;
    ExceptionType2: ExPattern2 [when ExGuard2] -> ExExpressions2;
    ...
  after
    AfterExpressions
  end
exit/1
Used to terminate the current process.
throw
Used as a documentation to the caller, to show that a function might throw this exception.
error
Crashing errors.

Fail Fast and Noisily, Fail Politely

In Erlang, when an error is detected internally by the system or is detected by program logic, the correct approach is to crash immediately and generate a meaningful error message.

(…)

Second, fail politely means that only the programmer should see the detailed error messages produced when a program crashes. A user of the program should never see these messages.

References

Armstrong, Joe. 2013. “Programming Erlang: Software for a Concurrent World.”
Laurent, Simon St. 2017. Introducing Erlang: Getting Started in Functional Programming. O’Reilly Media, Inc.

Links to this note