Erlang provides the primitives case and if which can be used for conditional evaluation in the body of a clause without having to use an additional function.

2.6.1. Case

The case expression allows choice between alternatives within the body of a clause and has the following syntax:

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

Firstly, Expr is evaluated, then, the value of Expr is sequentially matched against the patterns Pattern1, ..., PatternN until a match is found. If a match is found and the (optional) guard test succeeds, then the corresponding call sequence is evaluated. Note that case guards have the same form as function guards. The value of the case primitive is then the value of the selected sequence.

At least one pattern must match – if none of the patterns match then a run-time error will be generated and the error handling mechanism will be activated.

For example, suppose we have some function allocate(Resource) which tries to allocate Resource. Assume this function returns either {yes, Address} or no. Such a function could be used within a case construct 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 will be bound to the appropriate value returned by allocate/1.

To avoid the possibility of a match error we often add an additional pattern which is guaranteed to match as the last branch of the case primitive:

case Fn of
    ...
    _ ->
        true
end

2.6.2. If

if expressions have the syntax:

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

In this case the guards Guard1,... are evaluated sequentially. If a guard succeeds then the related sequence is evaluated. The result of this evaluation becomes the value of the if form. If guards have the same form as function guards. As with case it is an error if none of the guards succeeds. The guard test true can be added as a ‘catchall’ if necessary:

if
    ...
    true ->
        true
end

2.6.3. Examples of case and if

We can write the factorial function in a number of different ways using case and if.

Simplest:

factorial(0) -> 1;
    factorial(N) -> N * factorial(N - 1).

Using function guards:

factorial(0) -> 1;
factorial(N) when N > 0 -> N * factorial(N - 1).

Using if:

factorial(N) ->
    if
        N == 0 -> 1;
        N >  0 -> N * factorial(N-1)
    end.

Using case:

factorial(N) ->
    case N of
        0 -> 1;
        N when N > 0 ->
            N * factorial(N - 1)
    end.

Using variables to store temporary results:

factorial(0) ->
    1;
factorial(N) when N > 0 ->
    N1 = N - 1,
    F1 = factorial(N1),
    N * F1.

All of the above definitions are correct and equivalent – the choice among them is a matter of aesthetics.