bry*_*unt 7 compiler-construction syntax erlang scope try-catch
我正在使用Erlang R16B03.
这段代码:
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.
Run Code Online (Sandbox Code Playgroud)
生成以下编译器异常:
/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
Run Code Online (Sandbox Code Playgroud)
但是,如果我重新命名了第一次使用的变量名Result来Res,它编译罚款,如:
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.
Run Code Online (Sandbox Code Playgroud)
据我所知,变量在两个不同的范围内(try/catch和case).
这是编译器错误还是我无法正确理解Erlang语法?
这不是编译器错误.问题是在第一个例子中,你Result在两个地方使用:第一个在try,然后再在case.这些不是两个不同的范围,而是相同的范围.编译器抱怨,因为如果没有引发异常try,Result将绑定到erlang:port_info(Port)调用的结果,但如果该调用引发异常,Result则不会被绑定.这意味着它在内部的使用case将是不明确的,因为在第二case个子句中,如果它已经绑定,它将匹配,或者如果它尚未绑定则绑定到结果prim_file:list_dir(Port, Directory).
由于您已与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".
Run Code Online (Sandbox Code Playgroud)
即使Value仅在子句中绑定case,它仍然可以在外部范围中访问。请注意,Result变量也有界于 case 子句。