[erlang-questions] Fwd: [erlang-bugs] Incorrect scope for a variable

Ola Andersson A ola.a.andersson@REDACTED
Fri Feb 18 10:07:26 CET 2011


Very interesting indeed! 
But that still leaves the question about why the compiler does not give a warning when the case statements are enclosed by a tuple.
If the evaluation order is always strictly left to right I should get a warning with or without the tuple. 

Like this:

-module(a).

-compile([export_all]).

foo() -> {case 1 of X -> X end, case 2 of X -> X; _ -> 4 end}.

foo1() -> case 1 of X -> X end, case 2 of X -> X; _ -> 4 end.

Eshell V5.8.1  (abort with ^G)
1> c(a).
./a.erl:7: Warning: variable 'X' exported from 'case' (line 7)
{ok,a}
2>

The compiler only gives a warning about foo1.
It seems like the compiler also has problems with the tuple.
/OLA.

> -----Original Message-----
> From: Robert Virding [mailto:robert.virding@REDACTED] 
> Sent: den 18 februari 2011 00:57
> To: Joe Armstrong
> Cc: Bengt Kleberg; erlang-questions@REDACTED; Ola Andersson A
> Subject: Re: [erlang-questions] Fwd: [erlang-bugs] Incorrect 
> scope for a variable
> 
> This is most definitely a bug in the interpreter, erl_eval! 
> The compiler is doing the Right Thing.
> 
> The compiler evaluates the code strictly left-to-right which 
> it should do. When we finally got around to actually defining 
> the language we decided define a strict left-to-right 
> evaluation order in expressions. Not because it was 
> necessarily the best, it can preclude compiler optimisations, 
> but because then you would *know* exactly how expressions 
> would be evaluated.
> 
> And this is what the compiler does which explains the results 
> from the compiled code.
> 
> The interpreter does neither left-to-right nor right-to-left 
> but does try to evaluate them in parallel. So in the case of 
> the expression:
> 
> {case 1 of X -> X end, case 2 of X -> X; _ -> 4 end}
> 
> it evaluates each case separately with X unbound and then 
> tries to merge the values X of from the two cases. It does 
> something like:
> 
> begin V1 = case 1 of X1 -> X1 end, V2 = case 2 of X2 -> X2; _ 
> -> 4 end, X1 = X2, {V1,V2} end
> 
> Here X1 and X2 will have different values so the match/test 
> X1 = X2 will fail and generate a 'badmatch' error. N.B. if 
> you were to actually try and write this it would complain 
> that variable X2 is 'unsafe' as it is not exported from both 
> clauses but this rewrite is internal in the compiler.
> 
> I personally agree that exporting values from if/case/receive 
> is a Bad Thing (tm) but it does make some code a little more 
> compact. The 'unsafe' error is there to help you detect cases 
> which won't actually be wrong but could otherwise become 
> silently different. Which I can explain in a future message.
> 
> So the interpreter is wrong. The fix is actually quite simple.
> 
> Robert
> 
> 
> 
> ----- "Joe Armstrong" <erlang@REDACTED> wrote:
> 
> > On Thu, Feb 17, 2011 at 3:59 PM, Ola Andersson A < 
> > ola.a.andersson@REDACTED> wrote:
> > 
> > > Yes, that is what I would have expected too until I read Joes
> > explanation
> > > below regarding the same statement in the shell.
> > >
> > > The question is why the same statement gives a different result in
> > the
> > > shell as compared to when used in a module:
> > >
> > 
> > Very strange. Consider this module:
> > 
> > -module(a).
> > -compile(export_all).
> > 
> > foo() ->
> >     {case 1 of X -> X end, case 2 of X -> X end}.
> > 
> > foo1() ->
> >     {case 1 of X -> X end, case 2 of X -> X; _ -> 4 end}.
> > 
> > > a:foo().
> > ** exception error: no case clause matching 2
> >      in function  a:foo/0
> > > a:foo1().
> > {1,4}
> > 
> > The second example shows that order of evaluation withing 
> the tuple is 
> > left-to-right, if it had been parallel then the result should have 
> > been {1,2} (so my earlier explanation was wrong).
> > 
> > In the shell - both expressions result in errors
> > 
> > > f().
> > ok
> > >  {case 1 of X -> X end, case 2 of X -> X end}.
> > ** exception error: no match of right hand side value 1
> > > f().
> > ok
> > >  {case 1 of X -> X end, case 2 of X -> X; _ -> 4 end}.
> > ** exception error: no match of right hand side value 1
> > 
> > There is no way I can explain this - the compiled version looks 
> > correct and the version in the shell an error.
> > 
> > /Joe
> 
> --
> Robert Virding, Erlang Solutions Ltd.
> 
> 


More information about the erlang-questions mailing list