[erlang-questions] How about a new warning? Was: Re: trouble with erlang or erlang is a ghetto

Richard Carlsson carlsson.richard@REDACTED
Wed Aug 3 23:47:13 CEST 2011

On 08/03/2011 07:05 PM, Ulf Wiger wrote:
> According to the Barklund spec (page 62), it said that "a compiler
> must only accept a program if for any evaluation order, there will
> not be an applied occurrence of an unbound variable".
> "For example, in a context where X is unbound, the expression (X=8) +
> X should give a compile-time error."
> (And it does, too. I checked).

That's a slightly different thing - a requirement that any path that
reaches a use of a variable must first pass through a binding of that
variable. For instance:

   f(Y) ->
     case test(Y) of
        true -> X = 1;
        false -> ok

is not a valid program, because if the false path is taken, X is not
defined. The quote from the spec can be seen as a general design 
principle, which in practice is implemented by the scoping rules: For 
the case expression, a variable binding is only propagated out of a case 
if it is guaranteed to be bound in all clauses. For a function call (A+B 
is really a call to erlang:'+'(A,B)), all arguments are evaluated in the 
same ingoing environment , so even though the first argument to + 
creates a binding of X, this does not affect the environment for 
evaluating the second argument, in which X is not yet bound, so in both 
these examples the scoping rules forbid them.

Hence, the scoping rules partially determine the order of evaluation of 
the subexpressions, for the programs that pass this check (and assuming 
there is not a bug in the lower levels of the compiler), but on top of 
this, Erlang defines a strict left-to-right evaluation order for 
function arguments that has nothing to do with scoping. E.g.,

   {io:format("hello"), io:format("ulf")}

should always print "helloulf" and never "ulfhello".

An interesting twist on the example (X=8) + X is that if *both* 
arguments create a binding of the same variable, as in:

   (X=8) + (X=8)

then Erlang will first evaluate the subexpressions, then *check* that 
the results match so that a single agreed value of X can be exported out 
from the whole expression, and only in that case will it call + on the 
results. You can experiment with the following to see what I mean:

   f(Y) ->
     (X=Y) + (X=8).

(and no, it doesn't matter if the match against Y is on the right or 
left of the plus sign). f(8) will return 16, and f(Y) for any other Y 
will cause a badmatch. (I'm glad this worked - for a moment I was afraid 
that someone had forgotten to implement the check.)


More information about the erlang-questions mailing list