Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Erlang : variable 'Result' unsafe in 'try'

I'm using Erlang R16B03.

This code:

list_dir(Directory, Retries) when is_integer(Retries), Retries > 0 ->
    Port = get_efile_port(),
    try erlang:port_info(Port) of
        Result ->
            error_logger:info_msg("list_dir - erlang:port_info(~p) ->  ~p ", [Port,Result])
    catch
        _:Reason ->
             error_logger:info_msg("list_dir - erlang:port_info(~p) -> {error, ~p }",[Port,Reason])
    end,
    case prim_file:list_dir(Port, Directory) of
        {error, einval} ->
            error_logger:info_msg(" list_dir -  port : ~p , directory : ~p", [Port, Directory]),
            clear_efile_port(),
            list_dir(Directory, Retries-1);
        Result ->
            Result
    end.

Generates the following compiler exception:

/basho/riak/deps/bitcask/src/bitcask_fileops.erl:855: variable 'Result' unsafe in 'try' (line 843)
ERROR: compile failed while processing /basho/riak/deps/bitcask: rebar_abort
make: *** [compile] Error 1

But if I rename the first use of the variable name Result to Res, it compiles fine, e.g:

list_dir(Directory, Retries) when is_integer(Retries), Retries > 0 ->
    Port = get_efile_port(),
    try erlang:port_info(Port) of
        Res ->
            error_logger:info_msg("list_dir - erlang:port_info(~p) ->  ~p ", [Port,Res])
    catch
        _:Reason ->
             error_logger:info_msg("list_dir - erlang:port_info(~p) -> {error, ~p }",[Port,Reason])
    end,
    case prim_file:list_dir(Port, Directory) of
        {error, einval} ->
            error_logger:info_msg(" list_dir -  port : ~p , directory : ~p", [Port, Directory]),
            clear_efile_port(),
            list_dir(Directory, Retries-1);
        Result ->
            Result
    end.

As far as I can see the variables are within two different scopes (try/catch and case).

Is this a compiler bug or have I failed to understand the Erlang syntax correctly?

like image 975
bryan hunt Avatar asked Jul 22 '15 13:07

bryan hunt


Video Answer


1 Answers

This is not a compiler bug. The problem is that in the first example, you use Result in two places: first in the try, and then again in the case. These are not two different scopes, but the same scope. The compiler is complaining because if there's no exception raised in the try, Result will be bound to the result of the erlang:port_info(Port) call, but if that call raises an exception, Result will not be bound. This means its use within the case will be ambiguous, since in the second case clause it would be matched if it's already bound, or bound to the result of prim_file:list_dir(Port, Directory) if it's not already bound.

like image 119
Steve Vinoski Avatar answered Oct 19 '22 12:10

Steve Vinoski