[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
end,
g(X).
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.)
/Richard
More information about the erlang-questions
mailing list