[erlang-questions] variable exported from case in OTP 18
zxq9
zxq9@REDACTED
Tue Sep 29 13:42:19 CEST 2015
On 2015年9月29日 火曜日 11:06:48 Martin Koroudjiev wrote:
> Hello,
>
> I am confused why this code generates warning with the warn_export_vars
> option:
>
> -module(test).
>
> -export([test/1]).
>
> test(Mode) ->
> case Mode of
> r -> {ok, FP} = file:open("warn.erl", [read]);
> w -> {ok, FP} = file:open("warn.erl", [write])
> end,
> file:close(FP).
>
> compile:file("test.erl", [report, warn_export_vars]).
> test.erl:10: Warning: variable 'FP' exported from 'case' (line 6)
> {ok,test}
>
> Why this is better than this code:
>
> test(Mode) ->
> {ok, FP} =
> case Mode of
> r -> file:open("warn.erl", [read]);
> w -> file:open("warn.erl", [write])
> end,
> file:close(FP).
>
> which produces no warnings?
`case`, `if`, comprehensions, etc. are assumed to introduce a new scope of their own (whether they *actually* do or not). From this view you are accessing a variable defined within a different conceptual scope, even if it actually is accessible in this particular case.
The reason this has been made into a warning (and many tools compile with warnings-as-errors set) is that it is possible to not assign a variable you access outside the case in every branch of it and still get a clean compile:
foo() ->
case bar() of
{bing, Spam} -> eat(Spam);
{bong, Eggs} -> eat(Eggs)
end,
puke(Spam).
VS
foo() ->
Food = case bar() of
{bing, Spam} -> Spam;
{bong, Eggs} -> Eggs
end,
ok = eat(Food),
puke(Food).
Hey, look, one is more likely to be self-documenting now...
This has been discussed several times (here, for example: http://erlang.org/pipermail/erlang-questions/2014-March/078017.html), and because of the weirdness of case scope being one way (its a scope semantically and conceptually, but its not really) and list comprehensions being another (it really is a separate scope, but that's not how some other languages work) this has been made into a warning.
I remember the warning/error discussion happening, but can't find the notes for it (I had thought the "this is always a warning" thing came up with R16 or 17...?). :-( Anyway, what I remember of it was the danger of not assiging a variable in every branch, that being a silly thing to even worry with since cases are sorta-kinda their own scope, and case statements have a return value anyway that should be used as per the way everything else in Erlang works.
-Craig
More information about the erlang-questions
mailing list