[erlang-questions] Illegal Guard?

zxq9 <>
Fri Feb 5 14:09:15 CET 2016


On 2016年2月5日 金曜日 18:10:33 Theepan wrote:
> Team - Any idea?
> 
> 60> is_integer(A = 5).
> true
> 61> fun () when is_integer(A = 5) -> ok end.
> * 2: illegal guard expression
> 62> fun () when is_integer(5) -> ok end.
> #Fun<erl_eval.20.54118792>
> 63> fun (A = 5) when is_integer(A) -> ok end.
> #Fun<erl_eval.6.54118792>

I think it has to do with binding VS masking. That is to say, what part
of a function head is not yet referring to an external scope, so you can't
yet create a closure over an existing value:

  1> is_integer(A = 5).
  true
  2> B = fun() -> A end.
  #Fun<erl_eval.20.54118792>
  3> C = fun(A = 6) -> A end.
  #Fun<erl_eval.6.54118792>
  4> D = fun(A) -> A end.
  #Fun<erl_eval.6.54118792>

A is now actually assigned to 5 from our first statement -- which is
running within the context of an ongoing fun (I think). That being as
it may, anything assigned within the head of a function, apparently to
include guards, is masking whatever else existed. Its not about
is_integer/1 as much as it is about where it is used.

  5> A.
  5
  6> B().
  5
  7> C(6).
  6
  8> D(7).
  7

Now let's drop the current scope's memory of A:

  9> f(A).
  ok
  10> A.                                                                                                                                                                                                                                                                       
  * 1: variable 'A' is unbound
  11> B().
  5
  12> C(7).
  ** exception error: no function clause matching erl_eval:'-inside-an-interpreted-fun-'(7) 
  13> D(7).
  7

Now let's see what happens if we use an assignment within a guard within
a function's inner scope:

  14> E = fun(A) when is_integer(A) ->
  14>          case is_integer(Z = A) of
  14>             true -> Z;
  14>             false -> "strangeness"
  14>         end
  14>      end.
  #Fun<erl_eval.6.54118792>
  15> E(10).                                                                                               
  10

I don't know for sure, but this certainly leads me to believe it has
something to do with where the actual scoping boundary lies.

In other news... another thought crossed my mind...

WHY ARE YOU ASSIGNING INSIDE A GUARD?

Just to deepen the mystery because needlessly exploring corner cases
that should never occur in actual code is sort of funny to me...

  16> A = 5.
  5
  17> F = fun(A) when is_integer(A) ->
  17>          case is_integer(Z = A) of
  17>             true -> Z;
  17>             false -> "strangeness"
  17>         end
  17>      end.
  #Fun<erl_eval.6.54118792>
  18> F(5).
  5
  19> F(10).
  10
  20> A.
  5

Someone who really knows will get bored and give a real answer on Monday,
perhaps... ?

-Craig


More information about the erlang-questions mailing list