我正在使用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.
生成以下编译器异常:
/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
但是,如果我将变量名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.
据我所知,变量在两个不同的范围内(try / catch和case)。
这是编译错误还是我没能正确理解Erlang语法?
答案 0 :(得分:7)
这不是编译器错误。问题在于,在第一个示例中,您在两个位置使用Result
:首先在try
中,然后再在case
中。这些不是两个不同的范围,而是相同的范围。编译器抱怨,因为如果try
中没有引发异常,Result
将绑定erlang:port_info(Port)
调用的结果,但如果该调用引发异常,{{1}不受约束。这意味着它在Result
中的使用将是不明确的,因为在第二个case
子句中,如果它已经绑定将匹配,或者如果它尚未绑定则绑定到case
的结果
答案 1 :(得分:3)
try块本身返回一个值。所以你可以避免这样的情况
list_dir(Directory, Retries) when is_integer(Retries), Retries > 0 ->
Port = get_efile_port(),
Result = try erlang:port_info(Port) of
...
等
例如,这里是我正在进行的项目中的几行:
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
如果我要尝试分配&#34; F&#34;在&#34;尝试&#34;我得到了同样的错误!
答案 2 :(得分:2)
由于您已与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子句中。