Erlang: variable 'Result' is not safe in 'try'

I am 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.

Throws 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 Resultto Res, it compiles fine, for example:

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 in two different areas (try / catch and case).

Is this a compiler error, or was I unable to correctly understand the Erlang syntax?

+4
source share
3 answers

. , Result : try, case. , . , , try , Result erlang:port_info(Port), , Result . , case , case , prim_file:list_dir(Port, Directory), .

+8

Result, . . :

#! /usr/bin/env escript

main([What]) ->
    case What of
        Value when Value == "hello" ->
            Result = foo(Value),
            ok; 
        Value when Value == "goodbye" ->
            Result = foo(Value),
            ok  
    end,
    io:format("~p ~p",[Result, Value]).

foo("hello") ->
    "ohai";

foo("goodbye") ->
    "cya".

Value case, . Result, case.

+2

The try block itself returns a value. This way you can avoid situations like this

list_dir(Directory, Retries) when is_integer(Retries), Retries > 0 ->
    Port = get_efile_port(),
    Result = try erlang:port_info(Port) of
          ... 

and etc.

For example, here are a few lines from the project I'm working on now:

F = try
      python:call(P, 'python.repo_admin_cmd', 'repo_admin_cmd', [erlang:list_to_binary(Command) || Command <- Commands])
catch error:{python, _Class, _Argument, _StackTrace} ->
     error
end

If I tried to assign "F" inside the "try", I would get the same error as you!

+1
source

Source: https://habr.com/ru/post/1599097/


All Articles