1> Fact = fun F(0) -> 1
1> ; F(X) when is_integer(X), X > 0 -> X * F(X-1)
1> end.
#Fun<erl_eval.30.52032458>
2> Fact(5).
120
It’s strange how andprecedes> but still lets you define the function, when it’d be a bad argument on the toplevel:
1> Fact = fun F(0) -> 1
1> ; F(X) when is_integer(X) and X > 0 -> X * F(X-1)
1> end.
#Fun<erl_eval.30.52032458>
2> Fact(5).
** exception error: no function clause matching
erl_eval:'-inside-an-interpreted-fun-'(5)
3> is_integer(5) and 5 > 0.
** exception error: bad argument
in operator and/2
called as true and 5
I guess the trouble is that > is polymorphic, otherwise we wouldn’t need the is_integer test in the first place. But since everything is comparable, and atoms > integers, the guard will actually pass non-integers:
4> is_integer(false) and false > 0.
true
Minor wat there, so if you pass a boolean to the original function, you actually hang up on the subtraction inside:
3> Fact(false).
** exception error: an error occurred when evaluating an arithmetic expression
in operator -/2
called as false - 1
Here’s a third version, with a comma:
It’s strange how
andprecedes>but still lets you define the function, when it’d be a bad argument on the toplevel:I guess the trouble is that
>is polymorphic, otherwise we wouldn’t need the is_integer test in the first place. But since everything is comparable, and atoms>integers, the guard will actually pass non-integers:Minor wat there, so if you pass a boolean to the original function, you actually hang up on the subtraction inside:
Pretty strange to see when you forget the rules !
HA! Nice one with
Fact(false).