Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Overuse of guards in Erlang?

Tags:

erlang

I have the following function that takes a number like 5 and creates a list of all the numbers from 1 to that number so create(5). returns [1,2,3,4,5].

I have over used guards I think and was wondering if there is a better way to write the following:

create(N) ->
    create(1, N).

create(N,M) when N =:= M ->
    [N];
create(N,M) when N < M ->
    [N] ++ create(N + 1, M).
like image 627
dagda1 Avatar asked Dec 23 '22 04:12

dagda1


1 Answers

The guard for N < M can be useful. In general, you don't need a guard for equality; you can use pattern-matching.

create(N) -> create(1, N).

create(M, M) -> [M];
create(N, M) when N < M -> [N | create(N + 1, M)].

You also generally want to write functions so they are tail-recursive, in which the general idiom is to write to the head and then reverse at the end.

create(N) -> create(1, N, []).

create(M, M, Acc) -> lists:reverse([M | Acc]);
create(N, M, Acc) when N < M -> create(N + 1, M, [N | Acc]).

(Of course, with this specific example, you can alternatively build the results in the reverse order going down to 1 instead of up to M, which would make the lists:reverse call unnecessary.)

If create/2 (or create/3) is not exported and you put an appropriate guard on create/1, the extra N < M guard might be overkill. I generally only check on the exported functions and trust my own internal functions.

like image 173
Tadmas Avatar answered Jan 04 '23 08:01

Tadmas