1. 4

An Erlang WAT-Story about guards.

  1.  

  2. 2

    Here’s a third version, with a comma:

    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 and precedes > 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
    

    Pretty strange to see when you forget the rules !

    1. 1

      HA! Nice one with Fact(false).