Диализатор предупреждает об отсутствии локального возврата, когда функция 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]).