[erlang-questions] case expression scope

Anthony Ramine <>
Tue Mar 4 23:48:43 CET 2014


Hello,

This would be better written as:

maybe_log_error(Default, Fun) ->
  case Fun() of
    {ok,Result} ->
      Result;
    {error,Reason} ->
      lager:error("SOS ~p", [Reason]),
      Default
  end.

foo() ->
  ...
  V1 = maybe_log_error(BarDefault, fun bar/0),
  V2 = maybe_log_error(BazDefault, fun baz/0),
  ...

Sorry, but no luck for the filter.

-- 
Anthony Ramine

Le 4 mars 2014 à 23:41, Szoboszlay Dániel <> a écrit :

> On Tue, 04 Mar 2014 22:49:12 +0100, Richard A. O'Keefe <> 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
> _______________________________________________
> erlang-questions mailing list
> 
> http://erlang.org/mailman/listinfo/erlang-questions



More information about the erlang-questions mailing list