[erlang-questions] nested variable assignment : bug or the expected behaviour ?

Richard Carlsson carlsson.richard@REDACTED
Tue Jun 26 14:05:21 CEST 2012

On 06/26/2012 01:55 AM, James Churchman wrote:
> If i have a function like :
> f()->[J=100,J].
> Or put in the shell:
> {J=200,J}.
> Or
> erlang:'+'(J=10,J).
> Or any other combination of where i try to set a variable nested
> inside somewhere else, it will say "variable 'J' is unbound" .. is
> this the expected behaviour ?

Yes, it's expected. Each expression and subexpression in Erlang has an 
input environment and an output environment (which is the same as the 
input environment unless the expression creates additional bindings). 
Environments are chained so that in the comma-separated body of a 
clause, the output from one expression becomes the input of the next.

However, arguments to a single expression, such as f(A, B) or {A, B}, 
are always evaluated in the same input environment. Hence, even if you 
write f(X=1, X), where X is a previously unbound variable, both 
arguments are evaluated in the environment that does not contain X, and 
the compiler complains about the second X being unknown.

The output environment from an expression is the combination of the 
output environments from its subexpressions, so f(X=1, Y=2) exports both 
X and Y. To preserve the constraint that a variable occurring in more 
than one pattern has the same value independent of evaluation order, if 
you write f(X=a(), X=b()), the compiler will actually insert a test 
after the evaluation of the arguments to check that the intermediate 
results of a() and b() are in fact the same value and so either can be 
taken as the value of X.

As Richard O'Keefe said in his reply, Erlang uses strict left-to-right 
evaluation order also in function arguments (even where it to someone 
writing a compiler might seem to be backwards). This is to ensure that 
an Erlang program behaves the same regardless of compiler 
implementation, and to eliminate a source of confusion: programmers 
shouldn't have to remember a bunch of special cases where evaluation 
order is right-to-left or undefined. What you see is what you get.

But at the same time, the known evaluation order (with respect to side 
effects) should not be something that programmers can abuse to write 
unreadable code like f(1+g(X=h(Y),42),{foo,X}). Therefore, the scoping 
rules enforce that bindings are effectively treated as if the evaluation 
order of arguments was unknown, or could be changed from one version of 
Erlang to the next without changing the meaning of the program.


More information about the erlang-questions mailing list