[erlang-questions] case expression scope
Szoboszlay Dániel
dszoboszlay@REDACTED
Tue Mar 4 23:41:19 CET 2014
On Tue, 04 Mar 2014 22:49:12 +0100, Richard A. O'Keefe <ok@REDACTED>
wrote:
> No, you are still thinking in C/C++ terms.
> There are three things in Erlang that are scopes:
> - a function clause is a scope
> - a 'fun' is a scope
> - a list comprehension is a scope
Personally, I feel that these rules are neither convenient nor intuitive.
Mainly due to the last one, about the list comprehensions. I *know* that
list comprehensions are implemented with funs, hence the scoping, but it
still *looks like* a big exception from the "one function, one scope"
rule. And if you have background in any C-descendant language you would
almost certainly feel that cases, ifs, trys, begins etc. shall have their
own scopes too.
Some examples where I really miss them:
foo(Dict) ->
Value = case orddict:find(foo, Dict) of
{ok, Value} -> Value;
error -> calculate_very_expensive_default_value()
end,
...
Sorry, variable 'Value' is unsafe in 'case', please rename your internal
variable to 'Value1' or refactor this humble four-liner into a
get_foo_from_orddict/1 function, whichever you feel more inconvenient.
And we aren't done yet, let's add my favorite, the error-handling mess-up
to the mix!
foo() ->
...
V1 = case bar() of
{ok, Bar} ->
Bar;
{error, Reason} ->
lager:error("SOS ~p", [Reason]),
BarDefault
end,
V2 = case baz() of
{ok, Baz} ->
Baz;
{error, Reason} ->
lager:error("SOS ~p", [Reason]),
BazDefault
end,
...
Of course I know real programmers never put two cases in the same
function, but lazy people tend to. And lazy people also tend to use
convenient variable names like Reason or Error in error branches. And than
get compile errors or random badmatch crashes, depending on their code's
complexity.
The only benefit I see of *not starting* a new scope within a case is that
you can do this:
foo() ->
case bar() of
1 -> X = 1;
2 -> X = 2;
_ -> X = 0
end,
bar(X).
Which, in my opinion, is less readable than:
foo() ->
X = case bar() of
1 -> 1;
2 -> 2;
_ -> 0
end,
bar(X).
I hope these examples may pass the "this code is too trivial/ugly to even
notice your actual problem" filter with better luck than the previous
nominee. :)
Cheers,
Daniel
More information about the erlang-questions
mailing list