SoFunction
Updated on 2025-04-08

Introduction to Function and Process Control in Erlang

One: Function

1: In Erlang, two functions with the same name but different number of parameters are completely different functions.

2: Functions in other modules are called with fully qualified names:

Copy the codeThe code is as follows:

-module(sort1).
-export([reverse_sort/1, sort/1]).

reverse_sort(L) ->
        lists1:reverse(sort(L)).
sort(L) ->
        lists:sort(L).


3: The clauses are separated by semicolons [;], and end with [.] at the end.

4: Each function consists of a set of clauses. The clauses are separated by semicolon ";". Each clause contains a clause header, an optional protection form and clause body. The header of a clause contains a function name and a set of comma-separated parameters. When a function call occurs, the headers of the clauses in the function definition will be matched in sequence. All assertions when evaluating the protection form will be evaluated. If all assertions are true, the protection is true, otherwise it will fail. The evaluation order of each assertion in the protection formula is uncertain.

If the protection formula is true, the body of the clause will be evaluated. If the protected version fails, try the next candidate clause. Once the header and protection of the clause are matched successfully, the system will specify this clause and evaluate its body. The combination of clause header pattern and protection form can uniquely determine a correct clause.

The complete set of protected assertions is as follows:

Protective Conditions for establishment
atom(X) X is an atomic formula
constant(X) X is not a list or tuple
float(X) X is a floating point number
integer(X) X is an integer
list(X) X is a list or []
number X is an integer or floating point number
pid(X) X is a process identifier
port(X) X is a port
reference(X) X is a quote
tuple(X) X is a tuple
binary(X) X is a piece of binary data

In addition, some combinations of BIF and arithmetic expressions can also be used as protective expressions. They are:

Copy the codeThe code is as follows:

element/2, float/1, hd/1, length/1, round/1, self/0, ze/1
trunc/1,   tl/1, abs/1, node/1, node/0, nodes/0

The term comparison operators that can appear in the protection formula are as follows:

Operators describe type
X > Y X is greater than Y coerce
X < Y X less than Y coerce
X =< Y X less than or equal to Y coerce
X >= Y X is greater than or equal to Y coerce
X == Y X is equal to Y coerce
X /= Y X is not equal to Y coerce
X =:= Y X is equal to Y exact
X =/= Y X is not equal to Y exact

The working mechanism of the comparison operator is as follows: first evaluate both sides of the operator (for example, when there are arithmetic expressions on both sides of the expression or include BIF protected functions); then compare.

For comparison, the partial order relationship is defined as follows:

Copy the codeThe code is as follows:

number < atom < reference < port < pid < tuple < list

Tuples are sorted first by size and then by element. The comparison order of the list is first and then the tail.

If both parameters of the comparison operator are numeric types and the operator is coerce type, if one parameter is integer and the other is float, then integer will be converted to float and then compared.

Operators of exact type do not perform such conversions.

So 5.0 == 1 + 4 is true, while 5.0 =:= 4 + 1 is false.
Example of protection function clause:

Copy the codeThe code is as follows:

foo(X, Y, Z) when integer(X), integer(Y), integer(Z), X == Y + Z ->
foo(X, Y, Z) when list(X), hd(X) == {Y, length(Z)}  ->
foo(X, Y, Z) when {X, Y, size(Z)} == {a, 12, X} ->
foo(X) when list(X), hd(X) == c1, hd(tl(X)) == c2 ->

Note that no new variables can be introduced in the protection form.

2. Process control

case statement

The case expression allows selection among multiple options within the body of the clause, and the syntax is as follows:

Copy the codeThe code is as follows:

case Expr of
    Pattern1 [when Guard1] -> Seq1;
    Pattern2 [when Guard2] -> Seq2;
    ...
    PatternN [when GuardN] -> SeqN
end

First, evaluate Expr, and then, the value of Expr will be matched with the patterns Pattern1, Pattern2, and PatternN in turn until the match is successful. If a match is found and the (optional) protection formula holds, the corresponding call sequence will be evaluated. Note that the case protection form is the same as the function protection form. The value of the case primitive is the value of the selected sequence.

At least one pattern must be matched - otherwise a runtime error will be generated and an error handling mechanism in Chapter ?? will be raised.

For example, for example, I have a function allocate(Resource) for allocating a certain resource. Suppose this function returns only {yes, Address} or no. In this way, this function can be placed in a case structure:

Copy the codeThe code is as follows:

...
case allocate(Resource) of
    {yes,Address} when Address > 0, Address =< Max ->
        Sequence 1 ... ;
    no ->
        Sequence 2 ...
end
...

In Sequence 1 ..., the variable Address has been bound to the return result of allocate/1.

In order to avoid matching errors, we often append a pattern that must match as the last branch of the case primitive:

Copy the codeThe code is as follows:

case Fn of
    ...
    _ ->
        true
end

IF

The syntax of an if expression is as follows:

Copy the codeThe code is as follows:

if
    Guard1 ->
        Sequence1 ;
    Guard2 ->
        Sequence2 ;
    ...
end

In this case, the protective Guan1,... will be evaluated in sequence. If a protection formula is true, the sequence associated with it is evaluated. The evaluation result of this sequence is the result of the if structure. If protection is the same as the function protection. Like case, if a protection method is not valid, an error will be raised. If needed, you can add a protective assertion true as a trash bin:
Copy the codeThe code is as follows:

if
    ...
    true ->
        true
end

Arithmetic expressions

An arithmetic expression consists of the following operators:

Operators describe type Operand type Priority
+ X + X Monograph mix 1
- X - X Monograph mix 1
X * Y X * Y Binocular mix 2
X / Y X / Y (floating point division) Binocular mix 2
X div Y X Divide Y Binocular Integer 2
X rem Y X divided by Y remainder Binocular Integer 2
X band Y X and Y Binocular Integer 2
X + Y X + Y Binocular mix 3
X - Y X - Y Binocular mix 3
X bor Y X and Y positions or Binocular Integer 3
X bxor Y X and Y bit arithmetics Binocular Integer 3
X bsl N X Arithmetic shift left N bit Binocular Integer 3
X bsr N X Right shift N bit Binocular Integer 3

The monocular operator has one parameter, and the binocular operator has two parameters. Mix means that the parameters can be integer or float. The return value of the monocular operator is the same as its parameter type.

The binocular hybrid operator (i.e. * , - , + ) returns an object of type integer when the parameters are integer, and a float when the parameters contain at least one float. The floating point division operator/ always returns a float.

The parameters of the binocular integer operator (i.e. band , div , rem , bor , bxor , bsl , bsr ) must be integers, and their return value is also integers.

The order of evaluation depends on the operator's priority: first calculate the operator of priority 1, then the second priority 2, and so on. Expressions in brackets are evaluated first.

Operators with the same priority are evaluated from left to right.