Диализатор предупреждает об отсутствии локального возврата, когда функция fun() не возвращает

Я устраняю неполадки в моем коде Erlang, чтобы сделать его более эффективным. Но у меня есть некоторые проблемы с Dialyzer и я не знаю, как это исправить.

Первое о том, что "функция не имеет локального возврата". Пример кода здесь

print_list(File, List) ->
    {ok, Stream} = file:open(File, [write]),
    foreach(fun(X) -> do_something(X) end, List),
    file:close(Stream).

do_something(X) ->
     exit({error, X, "Type again"}).

Когда я запустил инструмент Dialyzer, он показал

foreach/1 не имеет локального возврата

Второй касается функции с сопоставлением с шаблоном:

handle_error() ->
    show_error(<<"Error due to wrong type">>).

show_error({error, Reason}) ->
    exit({error, Reason}); 
show_error({'EXIT', {aborted, {integer, _, _}}}) ->
    io:format("{'EXIT', {aborted, {integer, _, _}}}"); 
show_error({'EXIT', {suspend, {string, _, _}}}) ->
    throw({"EXIT", suspend}); 
show_error(Error) ->
    io:format("Error ~p~n",[Error]).

Когда я запустил Dialyzer, он показал

тип двоичных файлов при вызове функции отличается от первого типа {error, Reason}|{'EXIT', {aborted, {integer, _, _}}}

Диализатор не может перейти к последнему случаю, может соответствовать всем типам, отличным от 3 случаев выше.

1 ответ

Для первого выпуска, функция do_something/1 не возвращается, так как всегда выдает ошибку и останавливает вызывающий ее процесс. Таким образом, предупреждение предупреждает вас, что только первый элемент списка будет оцениваться в lists:foreach/2 вызов. Вы должны проверить, что это именно то, что вы хотите сделать.

Фактически, вы можете заменить весь код на exit({error, X, "Type again"}).

Во-вторых, я думаю, что show_error/1 является локальной функцией (не экспортируется), поэтому Dializer может проверить, что ни одно из 3 первых предложений никогда не будет соответствовать чему-либо.

[редактировать]

Чтобы проиллюстрировать то, что я сказал, следующая измененная версия не показывает ошибки.

  • Я добавил пункт к do_something/1 это имеет возвращаемое значение, поэтому в некоторых случаях функция будет возвращаться.
  • Я экспортировал show_error/1 так что функция может быть вызвана извне, и, следовательно, возможно, что одно из 3 первых предложений совпадает.
-module(try1).

-export ([print_list/2,handle_error/0,show_error/1]).


print_list(File, List) ->
    {ok, Stream} = file:open(File, [write]),
    lists:foreach(fun(X) -> do_something(X) end, List),
    file:close(Stream).

do_something(X) when is_integer(X) ->
     ok;
do_something(X) ->
     exit({error, X, "Type again"}).

handle_error() ->
    show_error(<<"Error due to wrong type">>).

show_error({error, Reason}) ->
    exit({error, Reason});
show_error({'EXIT', {aborted, {integer, _, _}}}) ->
    io:format("{'EXIT', {aborted, {integer, _, _}}}");
show_error({'EXIT', {suspend, {string, _, _}}}) ->
    throw({"EXIT", suspend});
show_error(Error) ->
    io:format("Error ~p~n",[Error]).
Другие вопросы по тегам