Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Erlang multiple Guards on `when`

Fellow stackoverflow-ers,

I am currently learning Erlang. Could someone point me why do I get an illegal guard expression with this guard?

add_new_prime(Idx, Primes, Ref) when length(Primes) =:= 0 ; math:sqrt(Idx) < hd(Primes) -> Ref ++ [Idx];

If I "un-optimise" it by doing only add_new_prime(Idx, Primes, Ref) when length(Primes) =:= 0 -> Ref ++ [Idx];

it works. I've seen multiple examples where there are more than one 'statement' per clause but can't see why mine is not working.

Thanks a lot!

like image 794
marctrem Avatar asked Dec 25 '22 07:12

marctrem


2 Answers

Please see:

The set of valid guard expressions (sometimes called guard tests) is a subset of the set of valid Erlang expressions. The reason for restricting the set of valid expressions is that evaluation of a guard expression must be guaranteed to be free of side effects. Valid guard expressions are:

the atom true, other constants (terms and bound variables), all regarded as false, calls to the BIFs specified below, term comparisons, arithmetic expressions, boolean expressions, and short-circuit expressions (andalso/orelse).

In you case, math:sqrt(Idx) is not a valid guard expression.

Read the documentation here: http://www.erlang.org/doc/reference_manual/expressions.html#id81357

like image 110
BlackMamba Avatar answered Jan 10 '23 22:01

BlackMamba


In addition to @BlackMamba's answer, the idiomatic Erlang approach would be:

add_new_prime(Idx, [], Ref) -> Ref ++ [Idx];
add_new_prime(Idx, [Prime | Primes], Ref) when Idx < Prime * Prime -> Ref ++ [Idx];
...

The inclusion of length/1 in guard tests has always been more than a bit dodgy. It's better taste to avoid it.

like image 22
Alexey Romanov Avatar answered Jan 10 '23 22:01

Alexey Romanov